From 6a7d17e3f28a7dbc3d28da5a989cdcd88d62d115 Mon Sep 17 00:00:00 2001 From: Daniel Klein Date: Wed, 21 Jan 2026 15:44:24 +0000 Subject: [PATCH 01/28] fix: update InfluxDB configuration for version 1 and add setup for version 2 with secure credentials Signed-off-by: Daniel Klein --- .devcontainer/docker-compose.yaml | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/.devcontainer/docker-compose.yaml b/.devcontainer/docker-compose.yaml index f6b0ab6..f9d049c 100644 --- a/.devcontainer/docker-compose.yaml +++ b/.devcontainer/docker-compose.yaml @@ -17,14 +17,14 @@ services: image: influxdb:1.11.8 container_name: influx_database_v1-rt ports: - - "8079:8086" + - "8030:8086" volumes: - - influxdb_data:/var/lib/influxdb + - influxdb_v1_data:/var/lib/influxdb restart: always environment: INFLUXDB_DB: submodel-db INFLUXDB_ADMIN_USER: admin - INFLUXDB_ADMIN_PASSWORD: fluid40 + INFLUXDB_ADMIN_PASSWORD: fluid40secure! INFLUXDB_USER: fluid40 INFLUXDB_USER_PASSWORD: wbEx!S!#4OHcN!5X healthcheck: @@ -34,6 +34,28 @@ services: retries: 5 start_period: 10s + influx_database_v2: + image: influxdb:2.7 + container_name: influx_database_v2-rt + ports: + - "8031:8086" + volumes: + - influxdb_v2_data:/var/lib/influxdb2 + restart: always + environment: + DOCKER_INFLUXDB_INIT_MODE: setup + DOCKER_INFLUXDB_INIT_USERNAME: admin + DOCKER_INFLUXDB_INIT_PASSWORD: fluid40secure! + DOCKER_INFLUXDB_INIT_ORG: fluid40-org + DOCKER_INFLUXDB_INIT_BUCKET: fluid40-bucket + DOCKER_INFLUXDB_INIT_ADMIN_TOKEN: wbEx!S!#4OHcN!5X + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8086/health"] + interval: 30s + timeout: 10s + retries: 5 + start_period: 10s + grafana: image: grafana/grafana:latest container_name: grafana-rt @@ -127,5 +149,6 @@ services: - RUNTIME_CONFIGURATION_FILE=./configuration/DevContainerEnv.json volumes: - influxdb_data: + influxdb_v1_data: + influxdb_v2_data: grafana_data: From 05560ed54f3a510c0ed3fe29b2af132555299e5c Mon Sep 17 00:00:00 2001 From: Daniel Klein Date: Wed, 21 Jan 2026 16:01:17 +0000 Subject: [PATCH 02/28] feat: add InfluxDB version 2 support and update configuration structure Signed-off-by: Daniel Klein --- configuration/DevContainerEnv.json | 13 +- docs/configuration.md | 115 ++++++++-------- runtime/core/server_initialization.py | 8 +- runtime/interfaces/influx_1_interface.py | 15 ++- runtime/interfaces/influx_2_interface.py | 160 +++++++++++++++++++++++ runtime/model/configuration.py | 1 + 6 files changed, 247 insertions(+), 65 deletions(-) create mode 100644 runtime/interfaces/influx_2_interface.py diff --git a/configuration/DevContainerEnv.json b/configuration/DevContainerEnv.json index 76fc0d6..5e4e355 100644 --- a/configuration/DevContainerEnv.json +++ b/configuration/DevContainerEnv.json @@ -15,13 +15,14 @@ "TrustEnv": false, "EncodedIds": false }, + "InfluxDbVersion": "1", "InfluxDb": { - "host": "influx_database_v1-rt", - "port": 8086, - "username": "fluid40", - "database": "submodel-db", - "connection_time_out": 60, - "trust_env": false + "Host": "influx_database_v1-rt", + "Port": 8086, + "Username": "fluid40", + "Database": "submodel-db", + "ConnectionTimeOut": 60, + "TrustEnv": false }, "PollingInterval": 5, "WriteInflux": true, diff --git a/docs/configuration.md b/docs/configuration.md index cb00b28..e9a2dd5 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -4,8 +4,11 @@ - [🌐 Overview](#-overview) - [πŸ“‘ Configuration Structure](#-configuration-structure) - [πŸ“‹ Configuration Parameters overview](#-configuration-parameters-overview) + - [1. General Settings](#1-general-settings) + - [2. Asset Connector Settings](#2-asset-connector-settings) + - [3. AAS Server Settings](#3-aas-server-settings) - [πŸ” AAS Server Authentication Settings](#-aas-server-authentication-settings) - - [πŸ—„οΈ Influx Database](#️-influx-database) + - [4. InfluxDB Settings](#4-influxdb-settings) - [πŸ”‘ Additional Passwords](#-additional-passwords) @@ -72,49 +75,59 @@ Example: } } }, + "InfluxDbVersion": "1", # Set the version of the used Influx DB "InfluxDb": { # Connection settings for the Influx database (optional) - "host": "influx_database", # The hostname or IP address of the InfluxDB server (required) - "port": 8086, # The port number of the InfluxDB server (required) - "username": "fluid40", # The username for the InfluxDB server (optional, default: "") - "database": "submodel-db", # The database name to use in InfluxDB (optional, default: "") - "connection_time_out": 100, # Connection establishment timeout in seconds (optional, default: 100) - "trust_env": true, # Disable proxy usage from environment (optional, default: true) + "Host": "influx_database", # The hostname or IP address of the InfluxDB server (required) + "Port": 8086, # The port number of the InfluxDB server (required) + "Username": "fluid40", # The username for the InfluxDB server (optional, default: "") + "Database": "submodel-db", # The database name to use in InfluxDB (optional, default: "") + "ConnectionTimeOut": 100, # Connection establishment timeout in seconds (optional, default: 100) + "TrustEnv": true, # Disable proxy usage from environment (optional, default: true) } } ``` -### πŸ“‹ Configuration Parameters overview -The configuration file is divided into several sections, each defining the parameters for a specific system component. Some fields are mandatory for the runtime to start, while others are optional and fall back to sensible defaults. The following table provides an overview of all available configuration parameters, updated to match the structure and naming from the Configuration Structure section: - -| Field | Description | Required | Default | -| ------------------------------------------------------- | ------------------------------------------------------------ | -------- | ---------------------- | -| **AasId** | Unique identifier of the Asset Administration Shell (AAS). | βœ… Yes | – | -| **PollingInterval** | Interval (in seconds) for retrieving values from the broker. | ❌ No | `5` | -| **PutSubmodel** | Enable putting changed dynamic submodels to AAS server | ❌ No | `false` | -| **AssetConnector.base_url** | Base URL of the Asset Connector REST API. | βœ… Yes | – | -| **AssetConnector.time_out** | API call timeout in seconds. | ❌ No | `200` | -| **AssetConnector.connection_time_out** | Connection establishment timeout in seconds. | ❌ No | `100` | -| **AssetConnector.trust_env** | Disable proxy usage from environment. | ❌ No | `true` | -| **AasServer.BaseUrl** | Base URL of the AAS server. | βœ… Yes | – | -| **AasServer.HttpsProxy** | HTTPS proxy. | ❌ No | `null` | -| **AasServer.HttpProxy** | HTTP proxy. | ❌ No | `null` | -| **AasServer.TimeOut** | API call timeout in seconds. | ❌ No | `200` | -| **AasServer.ConnectionTimeOut** | Connection establishment timeout in seconds. | ❌ No | `100` | -| **AasServer.SslVerify** | Verify TLS/SSL certificates. | ❌ No | `true` | -| **AasServer.TrustEnv** | Disable proxy usage from environment. | ❌ No | `true` | -| **AasServer.AuthenticationSettings.BasicAuth.Username** | Username for HTTP Basic Authentication. | ❌ No | `""` | -| **AasServer.AuthenticationSettings.OAuth.ClientId** | OAuth2 client identifier. | ❌ No | `""` | -| **AasServer.AuthenticationSettings.OAuth.TokenUrl** | OAuth2 token endpoint URL. | ❌ No | `""` | -| **AasServer.AuthenticationSettings.OAuth.GrantType** | OAuth2 grant type (`client_credentials` or `password`). | ❌ No | `"client_credentials"` | -| **InfluxDb.host** | Hostname or IP address of the InfluxDB server. | βœ… Yes | – | -| **InfluxDb.port** | Port number of the InfluxDB server. | βœ… Yes | – | -| **InfluxDb.username** | Username for the InfluxDB server. | ❌ No | `""` | -| **InfluxDb.database** | Database name to use in InfluxDB. | ❌ No | `""` | -| **InfluxDb.connection_time_out** | Connection establishment timeout in seconds. | ❌ No | `100` | -| **InfluxDb.trust_env** | Disable proxy usage from environment. | ❌ No | `true` | +### πŸ“‹ Configuration Parameters overview +The configuration file is divided into several sections, each defining the parameters for a specific system component. Some fields are mandatory for the runtime to start, while others are optional and fall back to sensible defaults. The following sub-chapters provide a detailed overview of all available configuration parameters, grouped by component: + +#### 1. General Settings +**Required** + +| Field | Description | Required | Default | +| ------------------- | ------------------------------------------------------------ | -------- | ------- | +| **AasId** | Unique identifier of the Asset Administration Shell (AAS). | βœ… Yes | – | +| **PollingInterval** | Interval (in seconds) for retrieving values from the broker. | ❌ No | `5` | +| **PutSubmodel** | Enable putting changed dynamic submodels to AAS server | ❌ No | `false` | + +#### 2. Asset Connector Settings +**Required** + +| Field | Description | Required | Default | +| -------------------------------------- | -------------------------------------------- | -------- | ------- | +| **AssetConnector.base_url** | Base URL of the Asset Connector REST API. | βœ… Yes | – | +| **AssetConnector.time_out** | API call timeout in seconds. | ❌ No | `200` | +| **AssetConnector.connection_time_out** | Connection establishment timeout in seconds. | ❌ No | `100` | +| **AssetConnector.trust_env** | Disable proxy usage from environment. | ❌ No | `true` | + +#### 3. AAS Server Settings +**Required** + +| Field | Description | Required | Default | +| ------------------------------------------------------- | ------------------------------------------------------- | -------- | ---------------------- | +| **AasServer.BaseUrl** | Base URL of the AAS server. | βœ… Yes | – | +| **AasServer.HttpsProxy** | HTTPS proxy. | ❌ No | `null` | +| **AasServer.HttpProxy** | HTTP proxy. | ❌ No | `null` | +| **AasServer.TimeOut** | API call timeout in seconds. | ❌ No | `200` | +| **AasServer.ConnectionTimeOut** | Connection establishment timeout in seconds. | ❌ No | `100` | +| **AasServer.SslVerify** | Verify TLS/SSL certificates. | ❌ No | `true` | +| **AasServer.TrustEnv** | Disable proxy usage from environment. | ❌ No | `true` | +| **AasServer.AuthenticationSettings.BasicAuth.Username** | Username for HTTP Basic Authentication. | ❌ No | `""` | +| **AasServer.AuthenticationSettings.OAuth.ClientId** | OAuth2 client identifier. | ❌ No | `""` | +| **AasServer.AuthenticationSettings.OAuth.TokenUrl** | OAuth2 token endpoint URL. | ❌ No | `""` | +| **AasServer.AuthenticationSettings.OAuth.GrantType** | OAuth2 grant type (`client_credentials` or `password`). | ❌ No | `"client_credentials"` | ### πŸ” AAS Server Authentication Settings @@ -152,16 +165,13 @@ The runtime supports multiple authentication methods for connecting to the AAS S } ``` -**Best Practices:** -- Always use environment variables for passwords, secrets, and tokens (see [Additional Passwords](#-additional-passwords)). -- Only include the authentication method(s) you intend to use in your configuration. -- If multiple authentication methods are configured, the runtime will use them in the following order of precedence: Bearer Token β†’ OAuth2 β†’ Basic Auth. -- Ensure your authentication server endpoints and credentials are correct and accessible from the runtime environment. +Passwords and secrets should be provided via environment variables, not in the configuration file. See the [Additional Passwords](#-additional-passwords) section for details. **References:** For detailed information about the AAS Server authentication configuration, see the [aas-http-client documentation](https://github.com/fluid40/aas-http-client/blob/main/docs/configuration.md). -### πŸ—„οΈ Influx Database +#### 4. InfluxDB Settings +**Optional** The InfluxDB integration enables the runtime to store time-series data for later analysis and visualization. This database connection is **optional**. If the `InfluxDb` section is omitted from your configuration file, the runtime will operate normally but will not persist any data to a database. @@ -169,16 +179,17 @@ The InfluxDB integration enables the runtime to store time-series data for later - If the `InfluxDb` node is **not set** in the configuration file, no data will be written to a database. - If the `InfluxDb` node is present but the specified database cannot be found or accessed, the runtime will continue operating, but data will not be written to the database. No critical errors will be raised, ensuring robust operation even if the database is temporarily unavailable. -**Best Practices:** -- Use environment variables to provide sensitive credentials (see [Additional Passwords](#-additional-passwords)). -- Ensure the InfluxDB server is reachable from the runtime environment. -- Regularly back up your InfluxDB data if persistence is critical. - -**Troubleshooting:** -- If data is not appearing in InfluxDB, check the runtime logs for connection errors or authentication issues. -- Verify that the `host`, `port`, and `database` values are correct and that the InfluxDB server is running. - -For more details on all available parameters, see the [Configuration Parameters overview](#-configuration-parameters-overview). +| Field | Description | Required | Default | +| ------------------------------ | ---------------------------------------------- | -------- | ------- | +| **InfluxDbVersion** | Set the version of the Influx DB | βœ… Yes | - | +| **InfluxDb.Host** | Hostname or IP address of the InfluxDB server. | βœ… Yes | – | +| **InfluxDb.Port** | Port number of the InfluxDB server. | βœ… Yes | – | +| **InfluxDb.Username** | Username for the InfluxDB server. | ❌ No | `""` | +| **InfluxDb.Database** | Database name to use in InfluxDB. | ❌ No | `""` | +| **InfluxDb.ConnectionTimeOut** | Connection establishment timeout in seconds. | ❌ No | `100` | +| **InfluxDb.TrustEnv** | Disable proxy usage from environment. | ❌ No | `true` | + +Passwords and secrets should be provided via environment variables, not in the configuration file. See the [Additional Passwords](#-additional-passwords) section for details. ## πŸ”‘ Additional Passwords diff --git a/runtime/core/server_initialization.py b/runtime/core/server_initialization.py index 73f7c0d..7fafb3a 100644 --- a/runtime/core/server_initialization.py +++ b/runtime/core/server_initialization.py @@ -123,7 +123,13 @@ def _connect_to_db(configuration: RuntimeConfiguration, aas: model.AssetAdminist logger.info("Get Influx DB password from environment variable 'RUNTIME_INFLUX_PW'") password = os.getenv("RUNTIME_INFLUX_PW") - client = influx_1_interface.create_client(configuration.influx_db_settings, password) + db_version: int = configuration.influx_db_version + + if db_version == 1: + client = influx_1_interface.create_client(configuration.influx_db_settings, password) + else: + logger.error(f"Unsupported InfluxDB version '{db_version}'. Only version 1 is supported.") + client = None if not client: logger.warning("No InfluxDB client available. Database interactions disabled.") diff --git a/runtime/interfaces/influx_1_interface.py b/runtime/interfaces/influx_1_interface.py index 6169b28..1d4cbbd 100644 --- a/runtime/interfaces/influx_1_interface.py +++ b/runtime/interfaces/influx_1_interface.py @@ -11,12 +11,14 @@ class InfluxClient(BaseModel): - host: str = Field(default="influx_database", description="The hostname or IP address of the InfluxDB server.") - port: int = Field(default=8086, description="The port number of the InfluxDB server.") - username: str = Field(default="", description="The username for the InfluxDB server.") - database: str = Field(default="", description="The database name to use in InfluxDB.") - connection_time_out: int = Field(default=100, description="Connection establishment timeout in seconds.") - trust_env: bool = Field(default=False, description="Disable proxy usage from environment.") + """Client for InfluxDB interactions.""" + + host: str = Field(default="influx_database", description="The hostname or IP address of the InfluxDB server.", alias="Host") + port: int = Field(default=8086, description="The port number of the InfluxDB server.", alias="Port") + username: str = Field(default="", description="The username for the InfluxDB server.", alias="Username") + database: str = Field(default="", description="The database name to use in InfluxDB.", alias="Database") + connection_time_out: int = Field(default=100, description="Connection establishment timeout in seconds.", alias="ConnectionTimeOut") + trust_env: bool = Field(default=False, description="Disable proxy usage from environment.", alias="TrustEnv") _client: InfluxDBClient = PrivateAttr(default=bool) _tag: str = PrivateAttr(default=str) @@ -36,6 +38,7 @@ def initialize(self, password: str) -> None: self._client = client def check_and_create_database(self): + """Check if the specified database exists, and create it if it does not.""" logger.debug(f"Check for database '{self.database}'.") dbs = [db["name"] for db in self._client.get_list_database()] if self.database not in dbs: diff --git a/runtime/interfaces/influx_2_interface.py b/runtime/interfaces/influx_2_interface.py new file mode 100644 index 0000000..1d4cbbd --- /dev/null +++ b/runtime/interfaces/influx_2_interface.py @@ -0,0 +1,160 @@ +import json +import logging +import time +from datetime import datetime + +import requests +from influxdb import InfluxDBClient +from pydantic import BaseModel, Field, PrivateAttr, ValidationError + +logger = logging.getLogger(__name__) + + +class InfluxClient(BaseModel): + """Client for InfluxDB interactions.""" + + host: str = Field(default="influx_database", description="The hostname or IP address of the InfluxDB server.", alias="Host") + port: int = Field(default=8086, description="The port number of the InfluxDB server.", alias="Port") + username: str = Field(default="", description="The username for the InfluxDB server.", alias="Username") + database: str = Field(default="", description="The database name to use in InfluxDB.", alias="Database") + connection_time_out: int = Field(default=100, description="Connection establishment timeout in seconds.", alias="ConnectionTimeOut") + trust_env: bool = Field(default=False, description="Disable proxy usage from environment.", alias="TrustEnv") + _client: InfluxDBClient = PrivateAttr(default=bool) + _tag: str = PrivateAttr(default=str) + + def initialize(self, password: str) -> None: + """Initialize the InfluxDB client with the given password. + + :param password: The password for the InfluxDB user. + """ + session = requests.Session() + session.trust_env = False + + client = InfluxDBClient(host=self.host, port=self.port, username=self.username, password=password, database=self.database, session=session) + + if not client: + logger.error("Could not create InfluxDB client.") + + self._client = client + + def check_and_create_database(self): + """Check if the specified database exists, and create it if it does not.""" + logger.debug(f"Check for database '{self.database}'.") + dbs = [db["name"] for db in self._client.get_list_database()] + if self.database not in dbs: + logger.debug(f"Create database '{self.database}'.") + self._client.create_database(self.database) + + logger.debug(f"Switch to database '{self.database}'.") + self._client.switch_database(self.database) + self._tag = "fluid40-runtime" + + def set_tag(self, tag: str) -> None: + """Set the source tag for data points. + + :param tag: The source tag to set. + """ + self._tag = tag.replace(" ", "_") + + def ping(self) -> bool: + """Ping the InfluxDB server to check if it's reachable. + + :return: True if the server is reachable, False otherwise. + """ + logger.debug(f"Pinging InfluxDB server '{self.host}:{self.port}'.") + if self._client is None: + logger.error("InfluxDB client is not initialized.") + return False + + try: + self._client.ping() + return True + except Exception as e: + logger.error(f"Failed to ping Influx DB server: {e}") + return False + + def write_data(self, data: dict, measurement_name: str, tags: dict | None = None) -> bool: + """Write data to the InfluxDB. + + :param data: The data to write, must include a 'timestamp' field in ISO format. + :param measurement_name: The name of the measurement. + :param tags: Optional tags to include with the data. + :return: True if the data was written successfully, False otherwise. + """ + logger.debug(f"Writing data to InfluxDB measurement '{measurement_name}' with tags: {tags}") + + if data is None or not isinstance(data, dict): + logger.debug(f"'{measurement_name}': Data must be a non-empty dictionary.") + return False + + if "timestamp" not in data: + logger.error(f"{measurement_name}: Data must include a 'timestamp' field.") + return False + + if tags is None: + tags = {"source": self._tag} + + point = { + "measurement": measurement_name, + "tags": tags, + "fields": data, + "time": int(datetime.fromisoformat(data["timestamp"].replace("Z", "+00:00")).timestamp() * 1e9), + } + logger.info(f"Writing data to InfluxDB measurement '{measurement_name}'\nTags:\n{tags}'\nValues:\n{json.dumps(data, indent=4)}") + success: bool = self._client.write_points([point], time_precision="n") + + if not success: + logger.error(f"Failed to write data point to InfluxDB: {point}") + return False + + return True + + +def create_client(config_dict: dict, password: str) -> InfluxClient: + """Create a HTTP client for a asset connector connection from a given configuration. + + :param config_dict: The configuration dictionary for the asset connector. + :raises ValidationError: If the configuration is invalid. + :return: A ConnectorClient instance or None if creation failed. + """ + logger.info("Create Influx Database client.") + + try: + config_string = json.dumps(config_dict, indent=4) + client = InfluxClient.model_validate_json(config_string) + except ValidationError as ve: + raise ValidationError(f"Invalid Influx DB configuration file: {ve}") from ve + + logger.info(f"Using Influx DB configuration: '{client.host}:{client.port}' | username: '{client.username}' | database: '{client.database}'.") + + client.initialize(password) + + connected = _establish_connection(client) + + if not connected: + return None + + client.check_and_create_database() + + return client + + +def _establish_connection(client: InfluxClient) -> bool: + start_time = time.time() + logger.info(f"Try to connect to Influx DB '{client.host}:{client.port}' for {client.connection_time_out} seconds") + counter: int = 0 + while True: + try: + root = client.ping() + if root: + logger.info(f"Connected to Influx DB at '{client.host}:{client.port}' successfully.") + return True + except requests.exceptions.ConnectionError: + pass + if time.time() - start_time > client.connection_time_out: + logger.error(f"Connection to Influx DB timed out after {client.connection_time_out} seconds.") + return False + + counter += 1 + logger.warning(f"Retrying connection to Influx DB (attempt: {counter})") + time.sleep(5) diff --git a/runtime/model/configuration.py b/runtime/model/configuration.py index 1b0f7fd..8383945 100644 --- a/runtime/model/configuration.py +++ b/runtime/model/configuration.py @@ -25,6 +25,7 @@ class RuntimeConfiguration(BaseModel): aas_server_settings: dict = Field(..., alias="AasServer") aas_id: str = Field(..., alias="AasId", description="The ID of the AAS.") asset_connector_settings: dict = Field(..., alias="AssetConnector") + influx_db_version: int = Field(default=0, alias="InfluxDbVersion") influx_db_settings: dict = Field(default={}, alias="InfluxDb") polling_interval: int = Field( default=5, alias="PollingInterval", description="Polling interval in seconds for retrieving values from the broker." From bdef9e1f409fae907e24faa03905d0dc81c3007c Mon Sep 17 00:00:00 2001 From: Daniel Klein Date: Wed, 21 Jan 2026 16:02:47 +0000 Subject: [PATCH 03/28] fix: update requirements for InfluxDB client compatibility Signed-off-by: Daniel Klein --- requirements.txt | Bin 580 -> 630 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/requirements.txt b/requirements.txt index d14cf28c01bf52c8fed9d85c1a23098590102e96..bf2e0f6922c263caae44c2b3b10fa506240620a6 100644 GIT binary patch delta 58 zcmX@Y@{MJK3zJbMLmopKLk>eJLj^+$LlT27Lo$$;$&d;ZFJZ7_uw^i0&|@%Rumq9@ J47?0n3;>a<3a Date: Thu, 22 Jan 2026 16:25:31 +0000 Subject: [PATCH 04/28] feat: update InfluxDB support to version 2 with new configuration and client integration Signed-off-by: Daniel Klein --- configuration/DevContainerEnv.json | 8 ++-- runtime/core/server_initialization.py | 8 +++- runtime/interfaces/influx_1_interface.py | 15 +++--- runtime/interfaces/influx_2_interface.py | 58 +++++++++++------------- 4 files changed, 44 insertions(+), 45 deletions(-) diff --git a/configuration/DevContainerEnv.json b/configuration/DevContainerEnv.json index 5e4e355..ae28afe 100644 --- a/configuration/DevContainerEnv.json +++ b/configuration/DevContainerEnv.json @@ -15,12 +15,12 @@ "TrustEnv": false, "EncodedIds": false }, - "InfluxDbVersion": "1", + "InfluxDbVersion": "2", "InfluxDb": { - "Host": "influx_database_v1-rt", - "Port": 8086, + "Url": "http://influx_database_v2-rt:8086/", "Username": "fluid40", - "Database": "submodel-db", + "Organization": "fluid40-org", + "Bucket": "fluid40-bucket", "ConnectionTimeOut": 60, "TrustEnv": false }, diff --git a/runtime/core/server_initialization.py b/runtime/core/server_initialization.py index 7fafb3a..55afeb8 100644 --- a/runtime/core/server_initialization.py +++ b/runtime/core/server_initialization.py @@ -9,7 +9,7 @@ from fastapi import HTTPException from runtime.core.utilities import aas_parser -from runtime.interfaces import asset_connector_interface, influx_1_interface +from runtime.interfaces import asset_connector_interface, influx_1_interface, influx_2_interface from runtime.model.classes import RuntimeStates from runtime.model.configuration import RuntimeConfiguration @@ -124,12 +124,16 @@ def _connect_to_db(configuration: RuntimeConfiguration, aas: model.AssetAdminist password = os.getenv("RUNTIME_INFLUX_PW") db_version: int = configuration.influx_db_version + client = None if db_version == 1: client = influx_1_interface.create_client(configuration.influx_db_settings, password) + + elif db_version == 2: + client = influx_2_interface.create_client(configuration.influx_db_settings, password) + else: logger.error(f"Unsupported InfluxDB version '{db_version}'. Only version 1 is supported.") - client = None if not client: logger.warning("No InfluxDB client available. Database interactions disabled.") diff --git a/runtime/interfaces/influx_1_interface.py b/runtime/interfaces/influx_1_interface.py index 1d4cbbd..d251eb9 100644 --- a/runtime/interfaces/influx_1_interface.py +++ b/runtime/interfaces/influx_1_interface.py @@ -13,9 +13,9 @@ class InfluxClient(BaseModel): """Client for InfluxDB interactions.""" - host: str = Field(default="influx_database", description="The hostname or IP address of the InfluxDB server.", alias="Host") - port: int = Field(default=8086, description="The port number of the InfluxDB server.", alias="Port") - username: str = Field(default="", description="The username for the InfluxDB server.", alias="Username") + host: str = Field(default="influx_database", description="The hostname or IP address of the InfluxDB 1 database.", alias="Host") + port: int = Field(default=8086, description="The port number of the InfluxDB database.", alias="Port") + username: str = Field(default="", description="The username for the InfluxDB database.", alias="Username") database: str = Field(default="", description="The database name to use in InfluxDB.", alias="Database") connection_time_out: int = Field(default=100, description="Connection establishment timeout in seconds.", alias="ConnectionTimeOut") trust_env: bool = Field(default=False, description="Disable proxy usage from environment.", alias="TrustEnv") @@ -73,15 +73,14 @@ def ping(self) -> bool: logger.error(f"Failed to ping Influx DB server: {e}") return False - def write_data(self, data: dict, measurement_name: str, tags: dict | None = None) -> bool: + def write_data(self, data: dict, measurement_name: str) -> bool: """Write data to the InfluxDB. :param data: The data to write, must include a 'timestamp' field in ISO format. :param measurement_name: The name of the measurement. - :param tags: Optional tags to include with the data. :return: True if the data was written successfully, False otherwise. """ - logger.debug(f"Writing data to InfluxDB measurement '{measurement_name}' with tags: {tags}") + logger.debug(f"Writing data to InfluxDB measurement '{measurement_name}' with tag: {self._tag}") if data is None or not isinstance(data, dict): logger.debug(f"'{measurement_name}': Data must be a non-empty dictionary.") @@ -91,8 +90,7 @@ def write_data(self, data: dict, measurement_name: str, tags: dict | None = None logger.error(f"{measurement_name}: Data must include a 'timestamp' field.") return False - if tags is None: - tags = {"source": self._tag} + tags = {"source": self._tag} point = { "measurement": measurement_name, @@ -100,6 +98,7 @@ def write_data(self, data: dict, measurement_name: str, tags: dict | None = None "fields": data, "time": int(datetime.fromisoformat(data["timestamp"].replace("Z", "+00:00")).timestamp() * 1e9), } + logger.info(f"Writing data to InfluxDB measurement '{measurement_name}'\nTags:\n{tags}'\nValues:\n{json.dumps(data, indent=4)}") success: bool = self._client.write_points([point], time_precision="n") diff --git a/runtime/interfaces/influx_2_interface.py b/runtime/interfaces/influx_2_interface.py index 1d4cbbd..2d20fc4 100644 --- a/runtime/interfaces/influx_2_interface.py +++ b/runtime/interfaces/influx_2_interface.py @@ -4,7 +4,9 @@ from datetime import datetime import requests -from influxdb import InfluxDBClient +from influxdb_client import InfluxDBClient, Point +from influxdb_client.client.write_api import SYNCHRONOUS +from influxdb_client.domain.bucket_retention_rules import BucketRetentionRules from pydantic import BaseModel, Field, PrivateAttr, ValidationError logger = logging.getLogger(__name__) @@ -13,12 +15,10 @@ class InfluxClient(BaseModel): """Client for InfluxDB interactions.""" - host: str = Field(default="influx_database", description="The hostname or IP address of the InfluxDB server.", alias="Host") - port: int = Field(default=8086, description="The port number of the InfluxDB server.", alias="Port") - username: str = Field(default="", description="The username for the InfluxDB server.", alias="Username") - database: str = Field(default="", description="The database name to use in InfluxDB.", alias="Database") + url: str = Field(default="influx_database", description="The base URL of the InfluxDB 2 database.", alias="Url") + organization: str = Field(default="", description="The Organization name to use in InfluxDB.", alias="Organization") + bucket: str = Field(default="", description="The Bucket name to use in InfluxDB.", alias="Bucket") connection_time_out: int = Field(default=100, description="Connection establishment timeout in seconds.", alias="ConnectionTimeOut") - trust_env: bool = Field(default=False, description="Disable proxy usage from environment.", alias="TrustEnv") _client: InfluxDBClient = PrivateAttr(default=bool) _tag: str = PrivateAttr(default=str) @@ -27,27 +27,24 @@ def initialize(self, password: str) -> None: :param password: The password for the InfluxDB user. """ - session = requests.Session() - session.trust_env = False - - client = InfluxDBClient(host=self.host, port=self.port, username=self.username, password=password, database=self.database, session=session) + client = InfluxDBClient(url=self.url, token=password, org=self.organization) if not client: logger.error("Could not create InfluxDB client.") self._client = client - def check_and_create_database(self): + def check_and_create_bucket(self): """Check if the specified database exists, and create it if it does not.""" - logger.debug(f"Check for database '{self.database}'.") - dbs = [db["name"] for db in self._client.get_list_database()] - if self.database not in dbs: - logger.debug(f"Create database '{self.database}'.") - self._client.create_database(self.database) + buckets_api = self._client.buckets_api() + + retention = BucketRetentionRules(type="expire", every_seconds=30 * 24 * 3600) - logger.debug(f"Switch to database '{self.database}'.") - self._client.switch_database(self.database) - self._tag = "fluid40-runtime" + buckets_api.create_bucket( + bucket_name=self.bucket, + org=self.organization, + retention_rules=retention, + ) def set_tag(self, tag: str) -> None: """Set the source tag for data points. @@ -61,7 +58,7 @@ def ping(self) -> bool: :return: True if the server is reachable, False otherwise. """ - logger.debug(f"Pinging InfluxDB server '{self.host}:{self.port}'.") + logger.debug(f"Pinging InfluxDB server '{self.url}'.") if self._client is None: logger.error("InfluxDB client is not initialized.") return False @@ -73,15 +70,14 @@ def ping(self) -> bool: logger.error(f"Failed to ping Influx DB server: {e}") return False - def write_data(self, data: dict, measurement_name: str, tags: dict | None = None) -> bool: + def write_data(self, data: dict, measurement_name: str) -> bool: """Write data to the InfluxDB. :param data: The data to write, must include a 'timestamp' field in ISO format. :param measurement_name: The name of the measurement. - :param tags: Optional tags to include with the data. :return: True if the data was written successfully, False otherwise. """ - logger.debug(f"Writing data to InfluxDB measurement '{measurement_name}' with tags: {tags}") + logger.debug(f"Writing data to InfluxDB measurement '{measurement_name}' with tags: {self._tag}") if data is None or not isinstance(data, dict): logger.debug(f"'{measurement_name}': Data must be a non-empty dictionary.") @@ -91,8 +87,7 @@ def write_data(self, data: dict, measurement_name: str, tags: dict | None = None logger.error(f"{measurement_name}: Data must include a 'timestamp' field.") return False - if tags is None: - tags = {"source": self._tag} + tags = {"source": self._tag} point = { "measurement": measurement_name, @@ -100,8 +95,11 @@ def write_data(self, data: dict, measurement_name: str, tags: dict | None = None "fields": data, "time": int(datetime.fromisoformat(data["timestamp"].replace("Z", "+00:00")).timestamp() * 1e9), } + logger.info(f"Writing data to InfluxDB measurement '{measurement_name}'\nTags:\n{tags}'\nValues:\n{json.dumps(data, indent=4)}") - success: bool = self._client.write_points([point], time_precision="n") + + write_api = self._client.write_api(write_options=SYNCHRONOUS) + success: bool = write_api.write(record=point, org=self.organization, bucket=self.bucket) if not success: logger.error(f"Failed to write data point to InfluxDB: {point}") @@ -125,7 +123,7 @@ def create_client(config_dict: dict, password: str) -> InfluxClient: except ValidationError as ve: raise ValidationError(f"Invalid Influx DB configuration file: {ve}") from ve - logger.info(f"Using Influx DB configuration: '{client.host}:{client.port}' | username: '{client.username}' | database: '{client.database}'.") + logger.info(f"Using Influx DB configuration: '{client.url}' | organization: '{client.organization}'.") client.initialize(password) @@ -134,20 +132,18 @@ def create_client(config_dict: dict, password: str) -> InfluxClient: if not connected: return None - client.check_and_create_database() - return client def _establish_connection(client: InfluxClient) -> bool: start_time = time.time() - logger.info(f"Try to connect to Influx DB '{client.host}:{client.port}' for {client.connection_time_out} seconds") + logger.info(f"Try to connect to Influx DB '{client.url}' for {client.connection_time_out} seconds") counter: int = 0 while True: try: root = client.ping() if root: - logger.info(f"Connected to Influx DB at '{client.host}:{client.port}' successfully.") + logger.info(f"Connected to Influx DB at '{client.url}' successfully.") return True except requests.exceptions.ConnectionError: pass From 4401bba3e97df1a84d9031d37c27a3e09e25f3de Mon Sep 17 00:00:00 2001 From: Daniel Klein Date: Fri, 23 Jan 2026 13:59:11 +0000 Subject: [PATCH 05/28] feat: implement InfluxDB v2 client interface and update InfluxDB interactions Signed-off-by: Daniel Klein --- .devcontainer/docker-compose.yaml | 2 +- configuration/DevContainerEnv.json | 10 +- runtime/core/core_process.py | 72 ++++++++++---- runtime/core/server_initialization.py | 21 ++-- runtime/interfaces/influx_1_interface.py | 60 ++++++----- runtime/interfaces/influx_2_interface.py | 121 +++++++++++++++-------- runtime/interfaces/influx_interface.py | 32 ++++++ runtime/model/classes.py | 16 +++ 8 files changed, 225 insertions(+), 109 deletions(-) create mode 100644 runtime/interfaces/influx_interface.py diff --git a/.devcontainer/docker-compose.yaml b/.devcontainer/docker-compose.yaml index f9d049c..4ff56a8 100644 --- a/.devcontainer/docker-compose.yaml +++ b/.devcontainer/docker-compose.yaml @@ -63,7 +63,7 @@ services: - "8076:3000" environment: GF_SECURITY_ADMIN_USER: admin - GF_SECURITY_ADMIN_PASSWORD: IDKFA-fluid40 + GF_SECURITY_ADMIN_PASSWORD: fluid40 depends_on: influx_database_v1: condition: service_healthy diff --git a/configuration/DevContainerEnv.json b/configuration/DevContainerEnv.json index ae28afe..df7c96a 100644 --- a/configuration/DevContainerEnv.json +++ b/configuration/DevContainerEnv.json @@ -1,5 +1,5 @@ { - "AasId": "https://fluid40.de/ids/shell/5793_5449_7830_4223", + "AasId": "https://fluid40.de/ids/aas/9911_6092_2508_3450", "AssetConnector": { "base_url": "http://asset_connector-rt:8000/", "time_out": 60, @@ -18,11 +18,9 @@ "InfluxDbVersion": "2", "InfluxDb": { "Url": "http://influx_database_v2-rt:8086/", - "Username": "fluid40", - "Organization": "fluid40-org", - "Bucket": "fluid40-bucket", - "ConnectionTimeOut": 60, - "TrustEnv": false + "Organization": "fluid40", + "Bucket": "submodel-db", + "ConnectionTimeOut": 60 }, "PollingInterval": 5, "WriteInflux": true, diff --git a/runtime/core/core_process.py b/runtime/core/core_process.py index ccd5231..fe066fd 100644 --- a/runtime/core/core_process.py +++ b/runtime/core/core_process.py @@ -1,5 +1,4 @@ import datetime -import json import logging from aas_http_client import SdkWrapper @@ -10,27 +9,44 @@ from runtime.core.server_initialization import RuntimeStates from runtime.interfaces.influx_1_interface import InfluxClient -from runtime.model.classes import PayloadValue +from runtime.model.classes import PayloadValue, ShellInfo router = APIRouter() logger = logging.getLogger(__name__) +counter = 1 + + +def _raise_counter(): + global counter + counter += 1 + + +def _get_counter() -> int: + return counter + def runtime_process(states: RuntimeStates): """Placeholder function for runtime process.""" + counter = _get_counter() + logger.info(f"Runtime process execution count: {counter}") + asset_values = get_asset_values(states) # Write asset values to InfluxDB if states.influx_client is not None: logger.info("Writing asset values to InfluxDB.") - _write_payloads_to_influx(asset_values, states.influx_client) + _write_payloads_to_influx(asset_values, states.influx_client, states.shell_info, counter) # Push changed submodels to AAS server if states.runtime_configuration.put_submodel: logger.info("Putting changed dynamic submodels to AAS server.") _push_submodels(states.wrapper, states.dynamic_submodel_cache) + # Increase counter + _raise_counter() + def get_asset_values(states: RuntimeStates): """Get the values from mapping configurations relations from broker. @@ -70,7 +86,7 @@ def get_asset_values(states: RuntimeStates): return asset_values -def _write_payloads_to_influx(payload_values: list[PayloadValue], influx_client: InfluxClient): +def _write_payloads_to_influx(payload_values: list[PayloadValue], influx_client: InfluxClient, shell_info: ShellInfo, counter: int): """Write payload values to InfluxDB. :param payload_values: List of PayloadValue instances. @@ -81,24 +97,40 @@ def _write_payloads_to_influx(payload_values: list[PayloadValue], influx_client: logger.warning("No payload values to write to InfluxDB.") return - payloads_dict: dict[str, dict[str, str]] = {} + fields: dict[str, dict[str, str]] = {} for payload_value in payload_values: - if payload_value.parent_name not in payloads_dict: - payloads_dict[payload_value.parent_name] = {} - payloads_dict[payload_value.parent_name][payload_value.property_name] = payload_value.value - - if influx_client: - try: - for measurement, fields in payloads_dict.items(): - # add timestamp if not present in fields - if "timestamp" not in fields: - fields["timestamp"] = datetime.datetime.now(tz=datetime.timezone.utc).isoformat() - - influx_client.write_data(fields, measurement) - except Exception as e: - logger.error(f"Could not write data to InfluxDB: {e}") - else: + fields[payload_value.property_name] = payload_value.value + + if influx_client is None: logger.error("InfluxDB client is not initialized.") + return + + measurement = shell_info.id_short.replace(" ", "_") + + pattern = "" + if "Pattern" in fields: + pattern = fields["Pattern"] + fields.pop("Pattern") + + if "Counter" in fields: + counter = fields["Counter"] + fields.pop("Counter") + + tags = { + "source": shell_info.display_name.replace(" ", "_"), + "counter": counter, + "pattern": pattern, + } + + try: + # Ensure timestamp field exists + if "timestamp" not in fields and "Timestamp" not in fields: + fields["timestamp"] = datetime.datetime.now(tz=datetime.timezone.utc).isoformat() + + influx_client.write_data(fields, measurement, tags) + + except Exception as e: + logger.error(f"Could not write data to InfluxDB: {e}") def _update_target_property_with_payload(payload_value: PayloadValue, wrapper: SdkWrapper, submodel_cache: dict[str, model.Submodel]): diff --git a/runtime/core/server_initialization.py b/runtime/core/server_initialization.py index 55afeb8..b7d470f 100644 --- a/runtime/core/server_initialization.py +++ b/runtime/core/server_initialization.py @@ -10,7 +10,8 @@ from runtime.core.utilities import aas_parser from runtime.interfaces import asset_connector_interface, influx_1_interface, influx_2_interface -from runtime.model.classes import RuntimeStates +from runtime.interfaces.influx_interface import IInfluxClient +from runtime.model.classes import RuntimeStates, ShellInfo from runtime.model.configuration import RuntimeConfiguration logger = logging.getLogger(__name__) @@ -28,6 +29,12 @@ def initialize_server(configuration: RuntimeConfiguration) -> RuntimeStates: # get the AAS aas = _get_aas(wrapper, configuration) + shell_info = ShellInfo( + id=aas.id, + id_short=aas.id_short, + display_name=_get_aas_display_name(aas), + ) + # get the AIMC submodel from the AAS logger.info("Get AIMC submodel from AAS.") aimc_submodel = aas_parser.get_aimc_submodel(wrapper, aas) @@ -39,9 +46,9 @@ def initialize_server(configuration: RuntimeConfiguration) -> RuntimeStates: asset_connector = _connect_to_asset_connector(configuration, aid_submodels) # connect to InfluxDB if enabled - influx_client = None + influx_client: IInfluxClient | None = None if configuration.influx_db_settings: - influx_client = _connect_to_db(configuration, aas) + influx_client = _connect_to_db(configuration) else: logger.warning("No InfluxDB settings provided. Database interactions disabled.") @@ -50,6 +57,7 @@ def initialize_server(configuration: RuntimeConfiguration) -> RuntimeStates: states.wrapper = wrapper states.asset_connector = asset_connector states.mapping_configurations = mapping_configurations + states.shell_info = shell_info states.influx_client = influx_client return states @@ -117,14 +125,14 @@ def _connect_to_aas_server(configuration: RuntimeConfiguration) -> SdkWrapper | return wrapper -def _connect_to_db(configuration: RuntimeConfiguration, aas: model.AssetAdministrationShell) -> influx_1_interface.InfluxClient | None: +def _connect_to_db(configuration: RuntimeConfiguration) -> IInfluxClient | None: logger.info("Connect to InfluxDB.") logger.info("Get Influx DB password from environment variable 'RUNTIME_INFLUX_PW'") password = os.getenv("RUNTIME_INFLUX_PW") db_version: int = configuration.influx_db_version - client = None + client: IInfluxClient | None = None if db_version == 1: client = influx_1_interface.create_client(configuration.influx_db_settings, password) @@ -139,9 +147,6 @@ def _connect_to_db(configuration: RuntimeConfiguration, aas: model.AssetAdminist logger.warning("No InfluxDB client available. Database interactions disabled.") return None - influx_tag = _get_aas_display_name(aas) - client.set_tag(influx_tag) - return client diff --git a/runtime/interfaces/influx_1_interface.py b/runtime/interfaces/influx_1_interface.py index d251eb9..d199b99 100644 --- a/runtime/interfaces/influx_1_interface.py +++ b/runtime/interfaces/influx_1_interface.py @@ -7,10 +7,12 @@ from influxdb import InfluxDBClient from pydantic import BaseModel, Field, PrivateAttr, ValidationError +from runtime.interfaces.influx_interface import IInfluxClient + logger = logging.getLogger(__name__) -class InfluxClient(BaseModel): +class InfluxClient(BaseModel, IInfluxClient): """Client for InfluxDB interactions.""" host: str = Field(default="influx_database", description="The hostname or IP address of the InfluxDB 1 database.", alias="Host") @@ -19,8 +21,7 @@ class InfluxClient(BaseModel): database: str = Field(default="", description="The database name to use in InfluxDB.", alias="Database") connection_time_out: int = Field(default=100, description="Connection establishment timeout in seconds.", alias="ConnectionTimeOut") trust_env: bool = Field(default=False, description="Disable proxy usage from environment.", alias="TrustEnv") - _client: InfluxDBClient = PrivateAttr(default=bool) - _tag: str = PrivateAttr(default=str) + _client: InfluxDBClient = PrivateAttr(default=None) def initialize(self, password: str) -> None: """Initialize the InfluxDB client with the given password. @@ -33,28 +34,23 @@ def initialize(self, password: str) -> None: client = InfluxDBClient(host=self.host, port=self.port, username=self.username, password=password, database=self.database, session=session) if not client: - logger.error("Could not create InfluxDB client.") + logger.error("Could not create InfluxDB v1 client.") self._client = client - def check_and_create_database(self): + def create_database(self): """Check if the specified database exists, and create it if it does not.""" - logger.debug(f"Check for database '{self.database}'.") + + logger.debug(f"Create database '{self.database}'") dbs = [db["name"] for db in self._client.get_list_database()] + + logger.debug(f"Check if database '{self.database}' already exists") if self.database not in dbs: - logger.debug(f"Create database '{self.database}'.") + logger.debug(f"Creating database '{self.database}'") self._client.create_database(self.database) logger.debug(f"Switch to database '{self.database}'.") self._client.switch_database(self.database) - self._tag = "fluid40-runtime" - - def set_tag(self, tag: str) -> None: - """Set the source tag for data points. - - :param tag: The source tag to set. - """ - self._tag = tag.replace(" ", "_") def ping(self) -> bool: """Ping the InfluxDB server to check if it's reachable. @@ -73,33 +69,34 @@ def ping(self) -> bool: logger.error(f"Failed to ping Influx DB server: {e}") return False - def write_data(self, data: dict, measurement_name: str) -> bool: + def write_data(self, fields: dict, measurement: str, tags: dict) -> bool: """Write data to the InfluxDB. - :param data: The data to write, must include a 'timestamp' field in ISO format. - :param measurement_name: The name of the measurement. + :param fields: The data to write, must include a 'timestamp' field in ISO format. + :param measurement: The name of the measurement. + :param tags: The tags to associate with the data point. :return: True if the data was written successfully, False otherwise. """ - logger.debug(f"Writing data to InfluxDB measurement '{measurement_name}' with tag: {self._tag}") + logger.debug(f"Writing data to InfluxDB measurement '{measurement}' with tags: {tags}") - if data is None or not isinstance(data, dict): - logger.debug(f"'{measurement_name}': Data must be a non-empty dictionary.") + if fields is None or not isinstance(fields, dict): + logger.debug(f"'{measurement}': Data must be a non-empty dictionary.") return False - if "timestamp" not in data: - logger.error(f"{measurement_name}: Data must include a 'timestamp' field.") + if "timestamp" not in fields and "Timestamp" not in fields: + logger.error(f"{measurement}: Data must include a 'timestamp' field.") return False - tags = {"source": self._tag} - point = { - "measurement": measurement_name, + "measurement": measurement, "tags": tags, - "fields": data, - "time": int(datetime.fromisoformat(data["timestamp"].replace("Z", "+00:00")).timestamp() * 1e9), + "fields": fields, + "time": int(datetime.fromisoformat(fields["timestamp"].replace("Z", "+00:00")).timestamp() * 1e9), } - logger.info(f"Writing data to InfluxDB measurement '{measurement_name}'\nTags:\n{tags}'\nValues:\n{json.dumps(data, indent=4)}") + logger.info( + f"Writing data to InfluxDB:\nMeasurement: '{measurement}'\nTags:\n{json.dumps(tags, indent=4)}'\nValues:\n{json.dumps(fields, indent=4)}" + ) success: bool = self._client.write_points([point], time_precision="n") if not success: @@ -109,10 +106,11 @@ def write_data(self, data: dict, measurement_name: str) -> bool: return True -def create_client(config_dict: dict, password: str) -> InfluxClient: +def create_client(config_dict: dict, password: str) -> IInfluxClient: """Create a HTTP client for a asset connector connection from a given configuration. :param config_dict: The configuration dictionary for the asset connector. + :param password: The password for the InfluxDB user. :raises ValidationError: If the configuration is invalid. :return: A ConnectorClient instance or None if creation failed. """ @@ -133,7 +131,7 @@ def create_client(config_dict: dict, password: str) -> InfluxClient: if not connected: return None - client.check_and_create_database() + client.create_database() return client diff --git a/runtime/interfaces/influx_2_interface.py b/runtime/interfaces/influx_2_interface.py index 2d20fc4..4d9b34a 100644 --- a/runtime/interfaces/influx_2_interface.py +++ b/runtime/interfaces/influx_2_interface.py @@ -2,6 +2,7 @@ import logging import time from datetime import datetime +from typing import Any import requests from influxdb_client import InfluxDBClient, Point @@ -9,49 +10,66 @@ from influxdb_client.domain.bucket_retention_rules import BucketRetentionRules from pydantic import BaseModel, Field, PrivateAttr, ValidationError +from runtime.interfaces.influx_interface import IInfluxClient + logger = logging.getLogger(__name__) -class InfluxClient(BaseModel): +class InfluxClient(BaseModel, IInfluxClient): """Client for InfluxDB interactions.""" url: str = Field(default="influx_database", description="The base URL of the InfluxDB 2 database.", alias="Url") - organization: str = Field(default="", description="The Organization name to use in InfluxDB.", alias="Organization") - bucket: str = Field(default="", description="The Bucket name to use in InfluxDB.", alias="Bucket") + organization: str = Field(..., description="The Organization name to use in InfluxDB.", alias="Organization") + bucket: str = Field(..., description="The Bucket name to use in InfluxDB.", alias="Bucket") connection_time_out: int = Field(default=100, description="Connection establishment timeout in seconds.", alias="ConnectionTimeOut") - _client: InfluxDBClient = PrivateAttr(default=bool) + _client: InfluxDBClient = PrivateAttr(default=None) _tag: str = PrivateAttr(default=str) + _organization_id: str = PrivateAttr(default=str) + _bucket_id: str = PrivateAttr(default=str) - def initialize(self, password: str) -> None: - """Initialize the InfluxDB client with the given password. + def initialize(self, token: str) -> None: + """Initialize the InfluxDB client with the given token. - :param password: The password for the InfluxDB user. + :param token: The token for the InfluxDB user. """ - client = InfluxDBClient(url=self.url, token=password, org=self.organization) + client = InfluxDBClient(url=self.url, token=token, org=self.organization) if not client: - logger.error("Could not create InfluxDB client.") + logger.error("Could not create InfluxDB v2 client.") + return + + orgs_api = client.organizations_api() + orgs: list = orgs_api.find_organizations(org=self.organization) + + if len(orgs) == 0 or orgs[0] is None: + logger.error(f"Organization '{self.organization}' not found in InfluxDB.") + else: + self._organization_id = orgs[0].id self._client = client - def check_and_create_bucket(self): - """Check if the specified database exists, and create it if it does not.""" + def create_database(self): + """Check if the specified bucket exists, and create it if it does not.""" + logger.debug(f"Create bucket '{self.bucket}'") buckets_api = self._client.buckets_api() - retention = BucketRetentionRules(type="expire", every_seconds=30 * 24 * 3600) + logger.debug(f"Check if bucket '{self.bucket}' already exists") + bucket = buckets_api.find_bucket_by_name(self.bucket) + + if bucket is not None: + logger.debug(f"Bucket '{self.bucket}' already exists") + self._bucket_id = bucket.id + return - buckets_api.create_bucket( + logger.debug(f"Creating bucket '{self.bucket}'") + retention = BucketRetentionRules(type="expire", every_seconds=30 * 24 * 3600) + bucket = buckets_api.create_bucket( bucket_name=self.bucket, - org=self.organization, + org_id=self._organization_id, retention_rules=retention, ) - def set_tag(self, tag: str) -> None: - """Set the source tag for data points. - - :param tag: The source tag to set. - """ - self._tag = tag.replace(" ", "_") + self._bucket_id = bucket.id def ping(self) -> bool: """Ping the InfluxDB server to check if it's reachable. @@ -64,54 +82,61 @@ def ping(self) -> bool: return False try: - self._client.ping() - return True + health = self._client.health() except Exception as e: logger.error(f"Failed to ping Influx DB server: {e}") return False - def write_data(self, data: dict, measurement_name: str) -> bool: + if health.status != "pass": + logger.error(f"InfluxDB server health check failed: {health.message}") + return False + + return True + + def write_data(self, fields: dict, measurement: str, tags: dict) -> bool: """Write data to the InfluxDB. - :param data: The data to write, must include a 'timestamp' field in ISO format. - :param measurement_name: The name of the measurement. + :param fields: The data to write, must include a 'timestamp' field in ISO format. + :param measurement: The name of the measurement. + :param tags: The tags to associate with the data point. :return: True if the data was written successfully, False otherwise. """ - logger.debug(f"Writing data to InfluxDB measurement '{measurement_name}' with tags: {self._tag}") + logger.debug(f"Writing data to InfluxDB measurement '{measurement}' with tags: {tags}") - if data is None or not isinstance(data, dict): - logger.debug(f"'{measurement_name}': Data must be a non-empty dictionary.") + if fields is None or not isinstance(fields, dict): + logger.debug(f"'{measurement}': Data must be a non-empty dictionary.") return False - if "timestamp" not in data: - logger.error(f"{measurement_name}: Data must include a 'timestamp' field.") + if "timestamp" not in fields and "Timestamp" not in fields: + logger.error(f"{measurement}: Data must include a 'timestamp' field.") return False - tags = {"source": self._tag} - point = { - "measurement": measurement_name, + "measurement": measurement, "tags": tags, - "fields": data, - "time": int(datetime.fromisoformat(data["timestamp"].replace("Z", "+00:00")).timestamp() * 1e9), + "fields": fields, + "time": int(datetime.fromisoformat(fields["timestamp"].replace("Z", "+00:00")).timestamp() * 1e9), } - logger.info(f"Writing data to InfluxDB measurement '{measurement_name}'\nTags:\n{tags}'\nValues:\n{json.dumps(data, indent=4)}") - - write_api = self._client.write_api(write_options=SYNCHRONOUS) - success: bool = write_api.write(record=point, org=self.organization, bucket=self.bucket) + logger.info( + f"Writing data to InfluxDB:\nMeasurement: '{measurement}'\nTags:\n{json.dumps(tags, indent=4)}'\nValues:\n{json.dumps(fields, indent=4)}" + ) - if not success: - logger.error(f"Failed to write data point to InfluxDB: {point}") + try: + write_api = self._client.write_api(write_options=SYNCHRONOUS) + write_api.write(record=point, bucket=self.bucket) + except Exception as e: + logger.error(f"Failed to write data point '{point}' to InfluxDB: {e}") return False return True -def create_client(config_dict: dict, password: str) -> InfluxClient: +def create_client(config_dict: dict, token: str) -> IInfluxClient: """Create a HTTP client for a asset connector connection from a given configuration. :param config_dict: The configuration dictionary for the asset connector. + :param token: The token for InfluxDB authentication. :raises ValidationError: If the configuration is invalid. :return: A ConnectorClient instance or None if creation failed. """ @@ -123,15 +148,25 @@ def create_client(config_dict: dict, password: str) -> InfluxClient: except ValidationError as ve: raise ValidationError(f"Invalid Influx DB configuration file: {ve}") from ve + if not client.organization.endswith("-org"): + logger.warning(f"Adjusting Influx DB organization name from '{client.organization}' to '{client.organization}-org'.") + client.organization = f"{client.organization}-org" + logger.info(f"Using Influx DB configuration: '{client.url}' | organization: '{client.organization}'.") - client.initialize(password) + client.initialize(token) connected = _establish_connection(client) if not connected: return None + try: + client.create_database() + except Exception as e: + logger.error(f"Failed to create InfluxDB database: {e}") + return None + return client diff --git a/runtime/interfaces/influx_interface.py b/runtime/interfaces/influx_interface.py new file mode 100644 index 0000000..1772da1 --- /dev/null +++ b/runtime/interfaces/influx_interface.py @@ -0,0 +1,32 @@ +"""Interface definitions for InfluxDB clients.""" + + +class IInfluxClient: + """Interface for InfluxDB clients.""" + + def initialize(self, password: str) -> None: + """Initialize the InfluxDB client with the given password. + + :param password: The password for the InfluxDB user. + """ + raise NotImplementedError + + def ping(self) -> bool: + """Ping the InfluxDB server to check if it's reachable. + + :return: True if the server is reachable, False otherwise. + """ + raise NotImplementedError + + def write_data(self, data: dict, measurement_name: str) -> bool: + """Write data to the InfluxDB. + + :param data: The data to write, must include a 'timestamp' field in ISO format. + :param measurement_name: The name of the measurement. + :return: True if the data was written successfully, False otherwise. + """ + raise NotImplementedError + + def create_database(self): + """Check if the specified database exists, and create it if it does not.""" + raise NotImplementedError diff --git a/runtime/model/classes.py b/runtime/model/classes.py index a47d2bc..84e4a1d 100644 --- a/runtime/model/classes.py +++ b/runtime/model/classes.py @@ -6,6 +6,21 @@ from runtime.model.configuration import RuntimeConfiguration +class ShellInfo: + """Class representing shell information for a model.""" + + def __init__(self, id: str, id_short: str, display_name: str): + """Initialize ShellInfo with given parameters. + + :param id: The unique identifier of the shell. + :param id_short: The short identifier of the shell. + :param display_name: The display name of the shell. + """ + self.id = id + self.id_short = id_short + self.display_name = display_name + + class RuntimeStates: """Class representing the runtime states of the server.""" @@ -15,6 +30,7 @@ class RuntimeStates: mapping_configurations: MappingConfigurations = None influx_client: influx_1_interface.InfluxClient = None dynamic_submodel_cache: dict[str, model.Submodel] = {} + shell_info: ShellInfo = None class PayloadValue: From 224b464de5787d36efef002a87b8635b48fde62d Mon Sep 17 00:00:00 2001 From: Daniel Klein Date: Fri, 23 Jan 2026 14:26:02 +0000 Subject: [PATCH 06/28] feat: add InfluxDB v2 datasource configuration with Flux support Signed-off-by: Daniel Klein --- .../provisioning/datasources/influxdb.yaml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.devcontainer/grafana/provisioning/datasources/influxdb.yaml b/.devcontainer/grafana/provisioning/datasources/influxdb.yaml index 52ee473..5f11787 100644 --- a/.devcontainer/grafana/provisioning/datasources/influxdb.yaml +++ b/.devcontainer/grafana/provisioning/datasources/influxdb.yaml @@ -18,3 +18,20 @@ datasources: isDefault: true editable: false version: 1 + + + - name: RuntimeInfluxDBv2 + uid: influxdb-v2 + type: influxdb + access: proxy + url: http://influx_database_v2-rt:8086 + + jsonData: + version: Flux + organization: fluid40-org + defaultBucket: fluid40-bucket + tlsSkipVerify: false + + + secureJsonData: + token: wbEx!S!#4OHcN!5X From d6ad985096b755ae0274dedc3313928d1cb73a2b Mon Sep 17 00:00:00 2001 From: Daniel Klein Date: Fri, 23 Jan 2026 14:29:08 +0000 Subject: [PATCH 07/28] fix: update InfluxDB v1 datasource credentials for consistency Signed-off-by: Daniel Klein --- .devcontainer/grafana/provisioning/datasources/influxdb.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.devcontainer/grafana/provisioning/datasources/influxdb.yaml b/.devcontainer/grafana/provisioning/datasources/influxdb.yaml index 5f11787..bbb49cf 100644 --- a/.devcontainer/grafana/provisioning/datasources/influxdb.yaml +++ b/.devcontainer/grafana/provisioning/datasources/influxdb.yaml @@ -6,7 +6,7 @@ datasources: access: proxy url: http://influx_database_v1-rt:8086 database: submodel-db - user: admin + user: fluid40 jsonData: tlsAuth: false tlsAuthWithCACert: false @@ -14,7 +14,7 @@ datasources: tlsCACert: "" tlsClientCert: "" tlsClientKey: "" - password: IDDQD-fluid40 + password: wbEx!S!#4OHcN!5X isDefault: true editable: false version: 1 From eb2334c895ad25bd079e9a965feb2ec729be00ff Mon Sep 17 00:00:00 2001 From: Daniel Klein Date: Fri, 23 Jan 2026 14:32:53 +0000 Subject: [PATCH 08/28] fix: standardize casing for AssetConnector configuration fields Signed-off-by: Daniel Klein --- configuration/DevContainerEnv.json | 8 ++++---- runtime/interfaces/asset_connector_interface.py | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/configuration/DevContainerEnv.json b/configuration/DevContainerEnv.json index df7c96a..6440cb0 100644 --- a/configuration/DevContainerEnv.json +++ b/configuration/DevContainerEnv.json @@ -1,10 +1,10 @@ { "AasId": "https://fluid40.de/ids/aas/9911_6092_2508_3450", "AssetConnector": { - "base_url": "http://asset_connector-rt:8000/", - "time_out": 60, - "connection_time_out": 60, - "trust_env": false + "BaseUrl": "http://asset_connector-rt:8000/", + "TimeOut": 60, + "ConnectionTimeOut": 60, + "TrustEnv": false }, "AasServer": { "BaseUrl": "http://javaserver-rt:8077/", diff --git a/runtime/interfaces/asset_connector_interface.py b/runtime/interfaces/asset_connector_interface.py index 870ba54..02feb55 100644 --- a/runtime/interfaces/asset_connector_interface.py +++ b/runtime/interfaces/asset_connector_interface.py @@ -19,10 +19,10 @@ class AssetConnectorClient(BaseModel): :return: A AssetConnectorClient instance. """ - base_url: str = Field(default="http://localhost:8000", description="The base URL of the Asset Connector REST API.") - time_out: int = Field(default=200, description="API call timeout in seconds.") - trust_env: bool = Field(default=True, description="Disable proxy usage from environment.") - connection_time_out: int = Field(default=100, description="Connection establishment timeout in seconds.") + base_url: str = Field(default="http://localhost:8000", description="The base URL of the Asset Connector REST API.", alias="BaseUrl") + time_out: int = Field(default=200, description="API call timeout in seconds.", alias="TimeOut") + trust_env: bool = Field(default=True, description="Disable proxy usage from environment.", alias="TrustEnv") + connection_time_out: int = Field(default=100, description="Connection establishment timeout in seconds.", alias="ConnectionTimeOut") _session: Session = PrivateAttr(default=None) def __init__(self, **data): From 46ffef83583b2c5fa927b90f06c30c9080e74764 Mon Sep 17 00:00:00 2001 From: Daniel Klein Date: Fri, 23 Jan 2026 15:07:25 +0000 Subject: [PATCH 09/28] feat: add changelog file with initial version details and improvements Signed-off-by: Daniel Klein --- .github/workflows/docker-image.yml | 1 + CHANGELOG.md | 6 ++++++ 2 files changed, 7 insertions(+) create mode 100644 CHANGELOG.md diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 02526c2..d2861d7 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -104,6 +104,7 @@ jobs: ### 🧩 Build Information - Docker image: `engineeringmethodsag/fluid-runtime:${{ steps.version.outputs.version }}-${{ steps.version.outputs.hash }}` - Latest tag: `engineeringmethodsag/fluid-runtime:latest` + - [Changelog](CHANGELOG.md) env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..5c9f169 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,6 @@ +# Changelog + +## [0.12.1] - 2026-01-20 +- ✨Feature: Ass support for InfluxDB database version 2 +- πŸš€Improvement: Improve structure of data written to database +- πŸš€Improvement: Standardization of configuration property names (see [configuration](docs/configuration.md)) From 0174daa6fe0d862db40320221b00b80c55c5815b Mon Sep 17 00:00:00 2001 From: Daniel Klein Date: Fri, 23 Jan 2026 15:12:24 +0000 Subject: [PATCH 10/28] fix: update changelog date and standardize README and backup documentation Signed-off-by: Daniel Klein --- CHANGELOG.md | 2 +- README.md | 43 +++---------------------------------- docs/backup.mdx | 57 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 41 deletions(-) create mode 100644 docs/backup.mdx diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c9f169..75eb8de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## [0.12.1] - 2026-01-20 +## [0.12.1] - 2026-01-23 - ✨Feature: Ass support for InfluxDB database version 2 - πŸš€Improvement: Improve structure of data written to database - πŸš€Improvement: Standardization of configuration property names (see [configuration](docs/configuration.md)) diff --git a/README.md b/README.md index cfc945b..40d5af3 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Runtime +# Micro-Service
aas_http_client @@ -9,52 +9,15 @@ [![CI](https://github.com/fluid40/runtime/actions/workflows/docker-image.yml/badge.svg?branch=main&cache-bust=1)](https://github.com/fluid40/runtime/actions) [![License](https://img.shields.io/badge/license-MIT-orange.svg)](LICENSE) -- [Runtime](#runtime) +- [Micro-Service](#micro-service) - [🌐 Overview](#-overview) - [πŸ”— Topics](#-topics) - - [🧩 Components](#-components) - - [🏭 Provided Environments](#-provided-environments) ## 🌐 Overview - -The runtime environment uses an AID submodel from a specific shell to configure an MQTT or OPC UA broker connection. The runtime then reads machine data from the broker at regular intervals. -If an Influx database has been connected, the data is stored there. -The runtime runs as a server component and provides REST endpoints to output the currently read machine data. +The microservice implements the use case of reading operating data from a tool, making this data available within the submodel structure, and optionally writing it to an InfluxDb database. ## πŸ”— Topics - πŸ› οΈ [Configuration](docs/configuration.md) - 🏭 [Environments](docs/environments.md) - -## 🧩 Components - -The runtime relies on several components to operate effectively. Each plays a specific role in data management and system integration: - -| Component | Requirement | Description | Link | -| ------------------------------ | ----------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | -| **AAS Server** | Required | Responsible for managing all Asset Administration Shells (AAS) and their submodels. | e.g. [Link](https://github.com/eclipse-basyx/basyx-java-server-sdk) | -| **Asset Administration Shell** | Required | An AAS hosted on the AAS Server, containing a fully configured AID and AIMC submodel. | | -| **Asset Connector** | Required | Interfaces with MQTT or OPC UA brokers to retrieve real-time machine data. | [Link](https://github.com/fluid40/asset-connector) | -| **InfluxDB** | Optional | Stores the data collected by the Asset Connector. | [Link](https://www.influxdata.com/) | - - -## 🏭 Provided Environments - -The runtime is provided in two different environments, depending on your use case and setup preferences: - -1. πŸ’» [DevContainer](docs/environments.md#-devcontainer) - - Provides all components pre-installed and ready to use. - - The runtime itself must still be started manually from the source code. - - For development, testing, or debugging individual components. - -The following table summarizes the key characteristics of the two provided environments: - -| Environment | Components Provided | Runtime Startup | Use Case / Purpose | -| ---------------- | ------------------- | ----------------------------------------- | ----------------------------------------------------- | -| **DevContainer** | All components | Must be started manually from source code | Development, testing, debugging individual components | - -
-Architecture -
- diff --git a/docs/backup.mdx b/docs/backup.mdx new file mode 100644 index 0000000..4c74bb5 --- /dev/null +++ b/docs/backup.mdx @@ -0,0 +1,57 @@ +# Micro-Service + +
+aas_http_client +
+ +--- + +[![CI](https://github.com/fluid40/runtime/actions/workflows/docker-image.yml/badge.svg?branch=main&cache-bust=1)](https://github.com/fluid40/runtime/actions) +[![License](https://img.shields.io/badge/license-MIT-orange.svg)](LICENSE) + +- [Runtime](#runtime) + - [🌐 Overview](#-overview) + - [πŸ”— Topics](#-topics) + - [🧩 Components](#-components) + - [🏭 Provided Environments](#-provided-environments) + +## 🌐 Overview +The micro service implements the use case + +## πŸ”— Topics + +- πŸ› οΈ [Configuration](docs/configuration.md) +- 🏭 [Environments](docs/environments.md) + + +## 🧩 Components + +The runtime relies on several components to operate effectively. Each plays a specific role in data management and system integration: + +| Component | Requirement | Description | Link | +| ------------------------------ | ----------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | +| **AAS Server** | Required | Responsible for managing all Asset Administration Shells (AAS) and their submodels. | e.g. [Link](https://github.com/eclipse-basyx/basyx-java-server-sdk) | +| **Asset Administration Shell** | Required | An AAS hosted on the AAS Server, containing a fully configured AID and AIMC submodel. | | +| **Asset Connector** | Required | Interfaces with MQTT or OPC UA brokers to retrieve real-time machine data. | [Link](https://github.com/fluid40/asset-connector) | +| **InfluxDB** | Optional | Stores the data collected by the Asset Connector. | [Link](https://www.influxdata.com/) | + + +## 🏭 Provided Environments + +The runtime is provided in two different environments, depending on your use case and setup preferences: + +1. πŸ’» [DevContainer](docs/environments.md#-devcontainer) + - Provides all components pre-installed and ready to use. + - The runtime itself must still be started manually from the source code. + - For development, testing, or debugging individual components. + +The following table summarizes the key characteristics of the two provided environments: + +| Environment | Components Provided | Runtime Startup | Use Case / Purpose | +| ---------------- | ------------------- | ----------------------------------------- | ----------------------------------------------------- | +| **DevContainer** | All components | Must be started manually from source code | Development, testing, debugging individual components | + +
+Architecture +
+ From 191fb356c663126964d5f12886d0f245cb5abfd0 Mon Sep 17 00:00:00 2001 From: Daniel Klein Date: Fri, 23 Jan 2026 15:53:14 +0000 Subject: [PATCH 11/28] feat: reorganize documentation by adding development environment details and removing outdated environments section Signed-off-by: Daniel Klein --- README.md | 5 ++- docs/configuration.md | 46 ++++++++---------------- docs/{environments.md => development.md} | 0 3 files changed, 19 insertions(+), 32 deletions(-) rename docs/{environments.md => development.md} (100%) diff --git a/README.md b/README.md index 40d5af3..eabbaa9 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,11 @@ ## 🌐 Overview The microservice implements the use case of reading operating data from a tool, making this data available within the submodel structure, and optionally writing it to an InfluxDb database. + ## πŸ”— Topics - πŸ› οΈ [Configuration](docs/configuration.md) -- 🏭 [Environments](docs/environments.md) +- 🏭 [Development](docs/development.md) + +## Resources diff --git a/docs/configuration.md b/docs/configuration.md index e9a2dd5..279464d 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -49,40 +49,24 @@ Example: { "AasId": "https://fluid40.de/ids/shell/8547_5433_6140_7422", # ID of the AAS "PollingInterval": 5, # Polling interval in seconds for retrieving values from the broker (optional, default: 5) - "PutSubmodel": true, # Enable putting changed dynamic submodels to AAS server - "AssetConnector": { # Connection settings for the Asset Connector - "base_url": "http://mqtt_connector:8000", # The base URL of the asset connector REST API (required) - "time_out": 200, # API call timeout in seconds (optional, default: 200) - "connection_time_out": 100, # Connection establishment timeout in seconds (optional, default: 100) - "trust_env": true, # Disable proxy usage from environment (optional, default: true) + "AssetConnector": { # Connection settings for the Asset Connector + "BaseUrl": "http://mqtt_connector:8000", # The base URL of the asset connector REST API (required) + "ConnectionTimeOut": 100, # Connection establishment timeout in seconds (optional, default: 100) + "trust_env": true, # Disable proxy usage from environment (optional, default: true) }, - "AasServer": { # Connection settings for the AAS Server - "BaseUrl": "http://javaserver:8077/", # Base URL of the AAS server (required) - "HttpsProxy": null, # HTTPS proxy (optional, default: null) - "HttpProxy": null, # HTTP proxy (optional, default: null) - "TimeOut": 200, # API call timeout in seconds (optional, default: 200) - "ConnectionTimeOut": 100, # Connection establishment timeout in seconds (optional, default: 100) - "SslVerify": true, # Verify TLS/SSL certificates (optional, default: true) - "TrustEnv": true, # Disable proxy usage from environment (optional, default: true) - "AuthenticationSettings": { # Authentication settings (optional) - "BasicAuth": { # Settings for basic auth - "Username": "admin" # Username for HTTP Basic Authentication - }, - "OAuth": { # Settings for oAuth2 - "ClientId": "my-client-id", # OAuth2 client identifier - "TokenUrl": "https://auth-server.example.com/oauth/token", # OAuth2 token endpoint URL - "GrantType": "client_credentials" # OAuth2 grant type (`client_credentials` or `password`) - } - } + "AasServer": { # Connection settings for the AAS Server + "BaseUrl": "http://javaserver:8077/", # Base URL of the AAS server (required) + "ConnectionTimeOut": 100, # Connection establishment timeout in seconds (optional, default: 100) + "SslVerify": true, # Verify TLS/SSL certificates (optional, default: true) + "TrustEnv": true, # Disable proxy usage from environment (optional, default: true) }, "InfluxDbVersion": "1", # Set the version of the used Influx DB - "InfluxDb": { # Connection settings for the Influx database (optional) - "Host": "influx_database", # The hostname or IP address of the InfluxDB server (required) - "Port": 8086, # The port number of the InfluxDB server (required) - "Username": "fluid40", # The username for the InfluxDB server (optional, default: "") - "Database": "submodel-db", # The database name to use in InfluxDB (optional, default: "") - "ConnectionTimeOut": 100, # Connection establishment timeout in seconds (optional, default: 100) - "TrustEnv": true, # Disable proxy usage from environment (optional, default: true) + "InfluxDb": { # Connection settings for the Influx database (optional) + "Host": "influx_database", # The hostname or IP address of the InfluxDB server (required) + "Port": 8086, # The port number of the InfluxDB server (required) + "Username": "fluid40", # The username for the InfluxDB server (optional, default: "") + "Database": "submodel-db", # The database name to use in InfluxDB (optional, default: "") + "TrustEnv": true, # Disable proxy usage from environment (optional, default: true) } } ``` diff --git a/docs/environments.md b/docs/development.md similarity index 100% rename from docs/environments.md rename to docs/development.md From 5420b45d11f02ea50c8c30253410f4ba7cd1d115 Mon Sep 17 00:00:00 2001 From: Daniel Klein Date: Mon, 26 Jan 2026 08:54:12 +0000 Subject: [PATCH 12/28] feat: enhance configuration documentation with detailed parameter sections and authentication settings Signed-off-by: Daniel Klein --- docs/configuration.md | 87 ++++++++++++++++++++++++++++++------------- 1 file changed, 62 insertions(+), 25 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index 279464d..2407e60 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -3,10 +3,15 @@ - [πŸ› οΈ Configuration](#️-configuration) - [🌐 Overview](#-overview) - [πŸ“‘ Configuration Structure](#-configuration-structure) - - [πŸ“‹ Configuration Parameters overview](#-configuration-parameters-overview) - - [1. General Settings](#1-general-settings) - - [2. Asset Connector Settings](#2-asset-connector-settings) - - [3. AAS Server Settings](#3-aas-server-settings) + - [πŸ“‹ Configuration Parameters overview](#-configuration-parameters-overview) + - [1. General Settings](#1-general-settings) + - [2. Asset Connector Settings](#2-asset-connector-settings) + - [3. AAS Server Settings](#3-aas-server-settings) + - [3.1 General Settings](#31-general-settings) + - [3.2 Authentication Settings](#32-authentication-settings) + - [3.2.1 HTTP Basic Authentication Settings](#321-http-basic-authentication-settings) + - [3.2.2 oAuth2 Settings](#322-oauth2-settings) + - [3.2.3 Bearer Token Settings](#323-bearer-token-settings) - [πŸ” AAS Server Authentication Settings](#-aas-server-authentication-settings) - [4. InfluxDB Settings](#4-influxdb-settings) - [πŸ”‘ Additional Passwords](#-additional-passwords) @@ -51,8 +56,9 @@ Example: "PollingInterval": 5, # Polling interval in seconds for retrieving values from the broker (optional, default: 5) "AssetConnector": { # Connection settings for the Asset Connector "BaseUrl": "http://mqtt_connector:8000", # The base URL of the asset connector REST API (required) + "TimeOut": 200, # API call timeout in seconds (optional, default to 200) "ConnectionTimeOut": 100, # Connection establishment timeout in seconds (optional, default: 100) - "trust_env": true, # Disable proxy usage from environment (optional, default: true) + "TrustEnv": true, # Disable proxy usage from environment (optional, default: true) }, "AasServer": { # Connection settings for the AAS Server "BaseUrl": "http://javaserver:8077/", # Base URL of the AAS server (required) @@ -73,46 +79,77 @@ Example: -### πŸ“‹ Configuration Parameters overview +## πŸ“‹ Configuration Parameters overview The configuration file is divided into several sections, each defining the parameters for a specific system component. Some fields are mandatory for the runtime to start, while others are optional and fall back to sensible defaults. The following sub-chapters provide a detailed overview of all available configuration parameters, grouped by component: -#### 1. General Settings +### 1. General Settings **Required** +The *General Settings* section defines the core parameters required for the runtime to operate. These include the unique identifier for the Asset Administration Shell (AAS) and the polling interval for retrieving values from the broker. Proper configuration of these fields ensures the runtime can identify itself and function at the desired update frequency. + | Field | Description | Required | Default | | ------------------- | ------------------------------------------------------------ | -------- | ------- | | **AasId** | Unique identifier of the Asset Administration Shell (AAS). | βœ… Yes | – | | **PollingInterval** | Interval (in seconds) for retrieving values from the broker. | ❌ No | `5` | -| **PutSubmodel** | Enable putting changed dynamic submodels to AAS server | ❌ No | `false` | -#### 2. Asset Connector Settings +### 2. Asset Connector Settings +**Required** + +The *Asset Connector Settings* section defines how the runtime communicates with the REST API of the Asset Connector micro service. These parameters specify the API endpoint, timeouts, and proxy handling, ensuring reliable and configurable integration with external asset data sources. + +| Field | Description | Required | Default | +| ------------------------------------ | -------------------------------------------- | -------- | ------- | +| **AssetConnector.BaseUrl** | Base URL of the Asset Connector REST API. | βœ… Yes | – | +| **AssetConnector.TimeOut** | API call timeout in seconds. | ❌ No | `200` | +| **AssetConnector.ConnectionTimeOut** | Connection establishment timeout in seconds. | ❌ No | `100` | +| **AssetConnector.TrustEnv** | Disable proxy usage from environment. | ❌ No | `true` | + +### 3. AAS Server Settings **Required** -| Field | Description | Required | Default | -| -------------------------------------- | -------------------------------------------- | -------- | ------- | -| **AssetConnector.base_url** | Base URL of the Asset Connector REST API. | βœ… Yes | – | -| **AssetConnector.time_out** | API call timeout in seconds. | ❌ No | `200` | -| **AssetConnector.connection_time_out** | Connection establishment timeout in seconds. | ❌ No | `100` | -| **AssetConnector.trust_env** | Disable proxy usage from environment. | ❌ No | `true` | -#### 3. AAS Server Settings + +#### 3.1 General Settings **Required** -| Field | Description | Required | Default | -| ------------------------------------------------------- | ------------------------------------------------------- | -------- | ---------------------- | -| **AasServer.BaseUrl** | Base URL of the AAS server. | βœ… Yes | – | -| **AasServer.HttpsProxy** | HTTPS proxy. | ❌ No | `null` | -| **AasServer.HttpProxy** | HTTP proxy. | ❌ No | `null` | -| **AasServer.TimeOut** | API call timeout in seconds. | ❌ No | `200` | -| **AasServer.ConnectionTimeOut** | Connection establishment timeout in seconds. | ❌ No | `100` | -| **AasServer.SslVerify** | Verify TLS/SSL certificates. | ❌ No | `true` | -| **AasServer.TrustEnv** | Disable proxy usage from environment. | ❌ No | `true` | +| Field | Description | Required | Default | +| ------------------------------- | -------------------------------------------- | -------- | ------- | +| **AasServer.BaseUrl** | Base URL of the AAS server. | βœ… Yes | – | +| **AasServer.HttpsProxy** | HTTPS proxy. | ❌ No | `null` | +| **AasServer.HttpProxy** | HTTP proxy. | ❌ No | `null` | +| **AasServer.TimeOut** | API call timeout in seconds. | ❌ No | `200` | +| **AasServer.ConnectionTimeOut** | Connection establishment timeout in seconds. | ❌ No | `100` | +| **AasServer.SslVerify** | Verify TLS/SSL certificates. | ❌ No | `true` | +| **AasServer.TrustEnv** | Disable proxy usage from environment. | ❌ No | `true` | + +### 3.2 Authentication Settings +**Optional** + +The AAS Server Communication supports three types of Authentification: + +- HTTP Basic Authentication +- oAuth2 +- Bearer Token + +#### 3.2.1 HTTP Basic Authentication Settings + + + | **AasServer.AuthenticationSettings.BasicAuth.Username** | Username for HTTP Basic Authentication. | ❌ No | `""` | + +HTTP Basic Authentication Password is set by environment variable `RUNTIME_BASIC_AUTH_PW` + +#### 3.2.2 oAuth2 Settings + | **AasServer.AuthenticationSettings.OAuth.ClientId** | OAuth2 client identifier. | ❌ No | `""` | | **AasServer.AuthenticationSettings.OAuth.TokenUrl** | OAuth2 token endpoint URL. | ❌ No | `""` | | **AasServer.AuthenticationSettings.OAuth.GrantType** | OAuth2 grant type (`client_credentials` or `password`). | ❌ No | `"client_credentials"` | +#### 3.2.3 Bearer Token Settings + + + ### πŸ” AAS Server Authentication Settings The runtime supports multiple authentication methods for connecting to the AAS Server, allowing secure integration in a variety of environments. Authentication credentials should be provided using environment variables whenever possible to avoid storing sensitive information in configuration files. From dd83a47fdd859c9731cecd8f833f3d6aec7a834b Mon Sep 17 00:00:00 2001 From: Daniel Klein Date: Mon, 26 Jan 2026 08:59:41 +0000 Subject: [PATCH 13/28] fix: update AasId and InfluxDbVersion in DevContainerEnv.json; enhance authentication documentation in configuration.md Signed-off-by: Daniel Klein --- configuration/DevContainerEnv.json | 12 ++-- docs/configuration.md | 94 ++++++++++++++---------------- 2 files changed, 49 insertions(+), 57 deletions(-) diff --git a/configuration/DevContainerEnv.json b/configuration/DevContainerEnv.json index 6440cb0..3bcd706 100644 --- a/configuration/DevContainerEnv.json +++ b/configuration/DevContainerEnv.json @@ -1,5 +1,6 @@ { - "AasId": "https://fluid40.de/ids/aas/9911_6092_2508_3450", + "AasId": "https://fluid40.de/ids/shell/5793_5449_7830_4223", + "PollingInterval": 5, "AssetConnector": { "BaseUrl": "http://asset_connector-rt:8000/", "TimeOut": 60, @@ -15,14 +16,11 @@ "TrustEnv": false, "EncodedIds": false }, - "InfluxDbVersion": "2", + "InfluxDbVersion": "1", "InfluxDb": { - "Url": "http://influx_database_v2-rt:8086/", + "Url": "http://influx_database_v1-rt:8086/", "Organization": "fluid40", "Bucket": "submodel-db", "ConnectionTimeOut": 60 - }, - "PollingInterval": 5, - "WriteInflux": true, - "PutSubmodel": false + } } diff --git a/docs/configuration.md b/docs/configuration.md index 2407e60..6992948 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -9,11 +9,10 @@ - [3. AAS Server Settings](#3-aas-server-settings) - [3.1 General Settings](#31-general-settings) - [3.2 Authentication Settings](#32-authentication-settings) - - [3.2.1 HTTP Basic Authentication Settings](#321-http-basic-authentication-settings) + - [3.2.1 Basic Authentication Settings](#321-basic-authentication-settings) - [3.2.2 oAuth2 Settings](#322-oauth2-settings) - [3.2.3 Bearer Token Settings](#323-bearer-token-settings) - - [πŸ” AAS Server Authentication Settings](#-aas-server-authentication-settings) - - [4. InfluxDB Settings](#4-influxdb-settings) + - [4. InfluxDB Settings](#4-influxdb-settings) - [πŸ”‘ Additional Passwords](#-additional-passwords) @@ -126,19 +125,41 @@ The *Asset Connector Settings* section defines how the runtime communicates with ### 3.2 Authentication Settings **Optional** -The AAS Server Communication supports three types of Authentification: +The runtime supports multiple authentication methods for connecting to the AAS Server, allowing secure integration in a variety of environments. Authentication credentials should be provided using environment variables whenever possible to avoid storing sensitive information in configuration files. -- HTTP Basic Authentication -- oAuth2 -- Bearer Token +**Supported Authentication Methods:** -#### 3.2.1 HTTP Basic Authentication Settings +1. **Basic Authentication** + - Set the username in the configuration under `AasServer.AuthenticationSettings.BasicAuth.Username`. + - Provide the password via the `RUNTIME_BASIC_AUTH_PW` environment variable. +2. **OAuth2 Client Credentials** + - Set the client ID, token URL, and grant type in the configuration under `AasServer.AuthenticationSettings.OAuth`. + - Provide the client secret via the `RUNTIME_OAUTH_SECRET` environment variable. +3. **Bearer Token Authentication** + - No username is required in the configuration. + - Provide the token via the `RUNTIME_BEARER_TOKEN` environment variable. + +Passwords and secrets should be provided via environment variables, not in the configuration file. See the [Additional Passwords](#-additional-passwords) section for details. + +**References:** +For detailed information about the AAS Server authentication configuration, see the [aas-http-client documentation](https://github.com/fluid40/aas-http-client/blob/main/docs/configuration.md). + +#### 3.2.1 Basic Authentication Settings | **AasServer.AuthenticationSettings.BasicAuth.Username** | Username for HTTP Basic Authentication. | ❌ No | `""` | -HTTP Basic Authentication Password is set by environment variable `RUNTIME_BASIC_AUTH_PW` +Provide the password via the `RUNTIME_BASIC_AUTH_PW` environment variable. + +Example: +```json +"AuthenticationSettings": { + "BasicAuth": { + "Username": "admin" + } +} +``` #### 3.2.2 oAuth2 Settings @@ -146,52 +167,25 @@ HTTP Basic Authentication Password is set by environment variable `RUNTIME_BASIC | **AasServer.AuthenticationSettings.OAuth.TokenUrl** | OAuth2 token endpoint URL. | ❌ No | `""` | | **AasServer.AuthenticationSettings.OAuth.GrantType** | OAuth2 grant type (`client_credentials` or `password`). | ❌ No | `"client_credentials"` | -#### 3.2.3 Bearer Token Settings - - - -### πŸ” AAS Server Authentication Settings +Provide the client secret via the `RUNTIME_OAUTH_SECRET` environment variable. -The runtime supports multiple authentication methods for connecting to the AAS Server, allowing secure integration in a variety of environments. Authentication credentials should be provided using environment variables whenever possible to avoid storing sensitive information in configuration files. - -**Supported Authentication Methods:** - -1. **Basic Authentication** - - Set the username in the configuration under `AasServer.AuthenticationSettings.BasicAuth.Username`. - - Provide the password via the `RUNTIME_BASIC_AUTH_PW` environment variable. - - Example: - ```json - "AuthenticationSettings": { - "BasicAuth": { - "Username": "admin" - } - } - ``` - -2. **Bearer Token Authentication** - - No username is required in the configuration. - - Provide the token via the `RUNTIME_BEARER_TOKEN` environment variable. +- Example: +```json +"AuthenticationSettings": { + "OAuth": { + "ClientId": "my-client-id", + "TokenUrl": "https://auth-server.example.com/oauth/token", + "GrantType": "client_credentials" + } +} +``` -3. **OAuth2 Client Credentials** - - Set the client ID, token URL, and grant type in the configuration under `AasServer.AuthenticationSettings.OAuth`. - - Provide the client secret via the `RUNTIME_OAUTH_SECRET` environment variable. - - Example: - ```json - "AuthenticationSettings": { - "OAuth": { - "ClientId": "my-client-id", - "TokenUrl": "https://auth-server.example.com/oauth/token", - "GrantType": "client_credentials" - } - } - ``` +#### 3.2.3 Bearer Token Settings -Passwords and secrets should be provided via environment variables, not in the configuration file. See the [Additional Passwords](#-additional-passwords) section for details. +Provide the token via the `RUNTIME_BEARER_TOKEN` environment variable. -**References:** -For detailed information about the AAS Server authentication configuration, see the [aas-http-client documentation](https://github.com/fluid40/aas-http-client/blob/main/docs/configuration.md). -#### 4. InfluxDB Settings +### 4. InfluxDB Settings **Optional** The InfluxDB integration enables the runtime to store time-series data for later analysis and visualization. This database connection is **optional**. If the `InfluxDb` section is omitted from your configuration file, the runtime will operate normally but will not persist any data to a database. From 005f3cba41595946c8fc705ef2639f83e4078961 Mon Sep 17 00:00:00 2001 From: Daniel Klein Date: Mon, 26 Jan 2026 09:01:55 +0000 Subject: [PATCH 14/28] refactor: streamline configuration documentation by reorganizing sections and removing redundant overview Signed-off-by: Daniel Klein --- docs/configuration.md | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index 6992948..be3dd4a 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -3,11 +3,10 @@ - [πŸ› οΈ Configuration](#️-configuration) - [🌐 Overview](#-overview) - [πŸ“‘ Configuration Structure](#-configuration-structure) - - [πŸ“‹ Configuration Parameters overview](#-configuration-parameters-overview) - - [1. General Settings](#1-general-settings) - - [2. Asset Connector Settings](#2-asset-connector-settings) - - [3. AAS Server Settings](#3-aas-server-settings) - - [3.1 General Settings](#31-general-settings) + - [1. General Settings](#1-general-settings) + - [2. Asset Connector Settings](#2-asset-connector-settings) + - [3. AAS Server Settings](#3-aas-server-settings) + - [3.1 General Settings](#31-general-settings) - [3.2 Authentication Settings](#32-authentication-settings) - [3.2.1 Basic Authentication Settings](#321-basic-authentication-settings) - [3.2.2 oAuth2 Settings](#322-oauth2-settings) @@ -76,13 +75,7 @@ Example: } ``` - - -## πŸ“‹ Configuration Parameters overview - -The configuration file is divided into several sections, each defining the parameters for a specific system component. Some fields are mandatory for the runtime to start, while others are optional and fall back to sensible defaults. The following sub-chapters provide a detailed overview of all available configuration parameters, grouped by component: - -### 1. General Settings +## 1. General Settings **Required** The *General Settings* section defines the core parameters required for the runtime to operate. These include the unique identifier for the Asset Administration Shell (AAS) and the polling interval for retrieving values from the broker. Proper configuration of these fields ensures the runtime can identify itself and function at the desired update frequency. @@ -92,7 +85,7 @@ The *General Settings* section defines the core parameters required for the runt | **AasId** | Unique identifier of the Asset Administration Shell (AAS). | βœ… Yes | – | | **PollingInterval** | Interval (in seconds) for retrieving values from the broker. | ❌ No | `5` | -### 2. Asset Connector Settings +## 2. Asset Connector Settings **Required** The *Asset Connector Settings* section defines how the runtime communicates with the REST API of the Asset Connector micro service. These parameters specify the API endpoint, timeouts, and proxy handling, ensuring reliable and configurable integration with external asset data sources. @@ -104,12 +97,12 @@ The *Asset Connector Settings* section defines how the runtime communicates with | **AssetConnector.ConnectionTimeOut** | Connection establishment timeout in seconds. | ❌ No | `100` | | **AssetConnector.TrustEnv** | Disable proxy usage from environment. | ❌ No | `true` | -### 3. AAS Server Settings +## 3. AAS Server Settings **Required** -#### 3.1 General Settings +### 3.1 General Settings **Required** | Field | Description | Required | Default | From df8f81951d5b33ad2e99a09576584550a42af842 Mon Sep 17 00:00:00 2001 From: Daniel Klein Date: Mon, 26 Jan 2026 09:02:26 +0000 Subject: [PATCH 15/28] fix: correct heading levels in InfluxDB settings section of configuration documentation Signed-off-by: Daniel Klein --- docs/configuration.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index be3dd4a..ba403ae 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -11,7 +11,7 @@ - [3.2.1 Basic Authentication Settings](#321-basic-authentication-settings) - [3.2.2 oAuth2 Settings](#322-oauth2-settings) - [3.2.3 Bearer Token Settings](#323-bearer-token-settings) - - [4. InfluxDB Settings](#4-influxdb-settings) + - [4. InfluxDB Settings](#4-influxdb-settings) - [πŸ”‘ Additional Passwords](#-additional-passwords) @@ -178,7 +178,7 @@ Provide the client secret via the `RUNTIME_OAUTH_SECRET` environment variable. Provide the token via the `RUNTIME_BEARER_TOKEN` environment variable. -### 4. InfluxDB Settings +## 4. InfluxDB Settings **Optional** The InfluxDB integration enables the runtime to store time-series data for later analysis and visualization. This database connection is **optional**. If the `InfluxDb` section is omitted from your configuration file, the runtime will operate normally but will not persist any data to a database. From 73df9094c700b95952f5824f4bf0352898693698 Mon Sep 17 00:00:00 2001 From: Daniel Klein Date: Mon, 26 Jan 2026 09:03:09 +0000 Subject: [PATCH 16/28] feat: add InfluxDB version sections to configuration documentation Signed-off-by: Daniel Klein --- docs/configuration.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/configuration.md b/docs/configuration.md index ba403ae..d84b4b9 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -12,6 +12,8 @@ - [3.2.2 oAuth2 Settings](#322-oauth2-settings) - [3.2.3 Bearer Token Settings](#323-bearer-token-settings) - [4. InfluxDB Settings](#4-influxdb-settings) + - [4.1 Influx DB version 1](#41-influx-db-version-1) + - [4.1 Influx DB version 2](#41-influx-db-version-2) - [πŸ”‘ Additional Passwords](#-additional-passwords) @@ -187,6 +189,8 @@ The InfluxDB integration enables the runtime to store time-series data for later - If the `InfluxDb` node is **not set** in the configuration file, no data will be written to a database. - If the `InfluxDb` node is present but the specified database cannot be found or accessed, the runtime will continue operating, but data will not be written to the database. No critical errors will be raised, ensuring robust operation even if the database is temporarily unavailable. +### 4.1 Influx DB version 1 + | Field | Description | Required | Default | | ------------------------------ | ---------------------------------------------- | -------- | ------- | | **InfluxDbVersion** | Set the version of the Influx DB | βœ… Yes | - | @@ -199,6 +203,8 @@ The InfluxDB integration enables the runtime to store time-series data for later Passwords and secrets should be provided via environment variables, not in the configuration file. See the [Additional Passwords](#-additional-passwords) section for details. +### 4.1 Influx DB version 2 + ## πŸ”‘ Additional Passwords Some components may require authentication. From 5de64e5bcec4123cf216d04933138cf490fed705 Mon Sep 17 00:00:00 2001 From: Daniel Klein Date: Mon, 26 Jan 2026 09:56:09 +0000 Subject: [PATCH 17/28] feat: update InfluxDB configuration and enhance payload writing with machine state Signed-off-by: Daniel Klein --- configuration/DevContainerEnv.json | 10 ++++--- docs/configuration.md | 46 ++++++++++++++++++++++++++---- runtime/core/core_process.py | 7 ++++- 3 files changed, 53 insertions(+), 10 deletions(-) diff --git a/configuration/DevContainerEnv.json b/configuration/DevContainerEnv.json index 3bcd706..a3f7999 100644 --- a/configuration/DevContainerEnv.json +++ b/configuration/DevContainerEnv.json @@ -18,9 +18,11 @@ }, "InfluxDbVersion": "1", "InfluxDb": { - "Url": "http://influx_database_v1-rt:8086/", - "Organization": "fluid40", - "Bucket": "submodel-db", - "ConnectionTimeOut": 60 + "Host": "influx_database_v1-rt", + "Port": 8086, + "Username": "fluid40", + "Database": "submodel-db", + "ConnectionTimeOut": 60, + "TrustEnv": false } } diff --git a/docs/configuration.md b/docs/configuration.md index d84b4b9..cbc6a23 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -158,9 +158,11 @@ Example: #### 3.2.2 oAuth2 Settings -| **AasServer.AuthenticationSettings.OAuth.ClientId** | OAuth2 client identifier. | ❌ No | `""` | -| **AasServer.AuthenticationSettings.OAuth.TokenUrl** | OAuth2 token endpoint URL. | ❌ No | `""` | -| **AasServer.AuthenticationSettings.OAuth.GrantType** | OAuth2 grant type (`client_credentials` or `password`). | ❌ No | `"client_credentials"` | +| Field | Description | Required | Default | +| ---------------------------------------------------- | ------------------------------------------------------- | -------- | ---------------------- | +| **AasServer.AuthenticationSettings.OAuth.ClientId** | OAuth2 client identifier. | ❌ No | `""` | +| **AasServer.AuthenticationSettings.OAuth.TokenUrl** | OAuth2 token endpoint URL. | ❌ No | `""` | +| **AasServer.AuthenticationSettings.OAuth.GrantType** | OAuth2 grant type (`client_credentials` or `password`). | ❌ No | `"client_credentials"` | Provide the client secret via the `RUNTIME_OAUTH_SECRET` environment variable. @@ -179,14 +181,13 @@ Provide the client secret via the `RUNTIME_OAUTH_SECRET` environment variable. Provide the token via the `RUNTIME_BEARER_TOKEN` environment variable. - ## 4. InfluxDB Settings **Optional** The InfluxDB integration enables the runtime to store time-series data for later analysis and visualization. This database connection is **optional**. If the `InfluxDb` section is omitted from your configuration file, the runtime will operate normally but will not persist any data to a database. **Behavior:** -- If the `InfluxDb` node is **not set** in the configuration file, no data will be written to a database. +- If the `InfluxDb` node is **not set** in the configuration file, no data will be written to a database. `InfluxDbVersion` - If the `InfluxDb` node is present but the specified database cannot be found or accessed, the runtime will continue operating, but data will not be written to the database. No critical errors will be raised, ensuring robust operation even if the database is temporarily unavailable. ### 4.1 Influx DB version 1 @@ -203,8 +204,41 @@ The InfluxDB integration enables the runtime to store time-series data for later Passwords and secrets should be provided via environment variables, not in the configuration file. See the [Additional Passwords](#-additional-passwords) section for details. +Example: +```json +"InfluxDbVersion": "1", +"InfluxDb": { + "Host": "influx_database_v1-rt", + "Port": 8086, + "Username": "fluid40", + "Database": "submodel-db", + "ConnectionTimeOut": 60, + "TrustEnv": false +} +``` + ### 4.1 Influx DB version 2 +| Field | Description | Required | Default | +| ------------------------------ | ---------------------------------------------- | -------- | ------- | +| **InfluxDbVersion** | Set the version of the Influx DB | βœ… Yes | - | +| **InfluxDb.Host** | Hostname or IP address of the InfluxDB server. | βœ… Yes | – | +| **InfluxDb.Port** | Port number of the InfluxDB server. | βœ… Yes | – | +| **InfluxDb.Username** | Username for the InfluxDB server. | ❌ No | `""` | +| **InfluxDb.Database** | Database name to use in InfluxDB. | ❌ No | `""` | +| **InfluxDb.ConnectionTimeOut** | Connection establishment timeout in seconds. | ❌ No | `100` | +| **InfluxDb.TrustEnv** | Disable proxy usage from environment. | ❌ No | `true` | + +Example: +```json +"InfluxDbVersion": "2", +"InfluxDb": { + "Url": "http://influx_database_v2-rt:8086/", + "Organization": "fluid40", + "Bucket": "submodel-db", + "ConnectionTimeOut": 60 +} +``` ## πŸ”‘ Additional Passwords Some components may require authentication. @@ -218,3 +252,5 @@ Instead of storing sensitive information in the configuration file, passwords mu | InfluxDB | `RUNTIME_INFLUX_PW` | Password used to authenticate with the InfluxDB | This approach keeps credentials secure and ensures they can be easily managed across different environments (development, staging, production). + + diff --git a/runtime/core/core_process.py b/runtime/core/core_process.py index fe066fd..9610d24 100644 --- a/runtime/core/core_process.py +++ b/runtime/core/core_process.py @@ -112,13 +112,18 @@ def _write_payloads_to_influx(payload_values: list[PayloadValue], influx_client: pattern = fields["Pattern"] fields.pop("Pattern") + machine_state = "" + if "MachineState" in fields: + machine_state = fields["MachineState"] + fields.pop("MachineState") + if "Counter" in fields: counter = fields["Counter"] - fields.pop("Counter") tags = { "source": shell_info.display_name.replace(" ", "_"), "counter": counter, + "machine_state": machine_state, "pattern": pattern, } From 6475c7f77d507f5644ceb9ad0a32fc36de886a83 Mon Sep 17 00:00:00 2001 From: Daniel Klein Date: Mon, 26 Jan 2026 09:57:40 +0000 Subject: [PATCH 18/28] fix: improve formatting of authentication settings table in configuration documentation Signed-off-by: Daniel Klein --- docs/configuration.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index cbc6a23..c01e610 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -143,7 +143,9 @@ For detailed information about the AAS Server authentication configuration, see #### 3.2.1 Basic Authentication Settings -| **AasServer.AuthenticationSettings.BasicAuth.Username** | Username for HTTP Basic Authentication. | ❌ No | `""` | +| Field | Description | Required | Default | +| ------------------------------------------------------- | --------------------------------------- | -------- | ------- | +| **AasServer.AuthenticationSettings.BasicAuth.Username** | Username for HTTP Basic Authentication. | ❌ No | `""` | Provide the password via the `RUNTIME_BASIC_AUTH_PW` environment variable. @@ -166,7 +168,7 @@ Example: Provide the client secret via the `RUNTIME_OAUTH_SECRET` environment variable. -- Example: +Example: ```json "AuthenticationSettings": { "OAuth": { From 295d7fec82a48b85f7095ba9303393ea24315f9a Mon Sep 17 00:00:00 2001 From: Daniel Klein Date: Mon, 26 Jan 2026 10:00:11 +0000 Subject: [PATCH 19/28] feat: enhance configuration documentation with improved structure and additional references Signed-off-by: Daniel Klein --- docs/configuration.md | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index c01e610..5172b73 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -51,20 +51,20 @@ All other parameters are optional and fall back to reasonable defaults. Example: ```yml -{ - "AasId": "https://fluid40.de/ids/shell/8547_5433_6140_7422", # ID of the AAS - "PollingInterval": 5, # Polling interval in seconds for retrieving values from the broker (optional, default: 5) - "AssetConnector": { # Connection settings for the Asset Connector - "BaseUrl": "http://mqtt_connector:8000", # The base URL of the asset connector REST API (required) - "TimeOut": 200, # API call timeout in seconds (optional, default to 200) - "ConnectionTimeOut": 100, # Connection establishment timeout in seconds (optional, default: 100) - "TrustEnv": true, # Disable proxy usage from environment (optional, default: true) +{ # General Setting + "AasId": "https://fluid40.de/ids/shell/8547_5433_6140_7422", + "PollingInterval": 5, + "AssetConnector": { # Asset Connector Settings + "BaseUrl": "http://mqtt_connector:8000", + "TimeOut": 200, + "ConnectionTimeOut": 100, + "TrustEnv": true, }, - "AasServer": { # Connection settings for the AAS Server - "BaseUrl": "http://javaserver:8077/", # Base URL of the AAS server (required) - "ConnectionTimeOut": 100, # Connection establishment timeout in seconds (optional, default: 100) - "SslVerify": true, # Verify TLS/SSL certificates (optional, default: true) - "TrustEnv": true, # Disable proxy usage from environment (optional, default: true) + "AasServer": { # AAS Server Settings + "BaseUrl": "http://javaserver:8077/", + "ConnectionTimeOut": 100, + "SslVerify": true, + "TrustEnv": true, }, "InfluxDbVersion": "1", # Set the version of the used Influx DB "InfluxDb": { # Connection settings for the Influx database (optional) @@ -102,7 +102,9 @@ The *Asset Connector Settings* section defines how the runtime communicates with ## 3. AAS Server Settings **Required** - +**References:** +For the connection to the AAS Server the [aas-http-client](https://github.com/fluid40/aas-http-client) package is used. +For detailed information about the AAS Server configuration, see the [aas-http-client documentation](https://github.com/fluid40/aas-http-client/blob/main/docs/configuration.md). ### 3.1 General Settings **Required** @@ -138,8 +140,7 @@ The runtime supports multiple authentication methods for connecting to the AAS S Passwords and secrets should be provided via environment variables, not in the configuration file. See the [Additional Passwords](#-additional-passwords) section for details. -**References:** -For detailed information about the AAS Server authentication configuration, see the [aas-http-client documentation](https://github.com/fluid40/aas-http-client/blob/main/docs/configuration.md). + #### 3.2.1 Basic Authentication Settings From 9d561886fac0f9b9772ac45ca024e740a422f6fd Mon Sep 17 00:00:00 2001 From: Daniel Klein Date: Mon, 26 Jan 2026 10:04:25 +0000 Subject: [PATCH 20/28] fix: correct InfluxDB section headings and improve configuration parameter descriptions Signed-off-by: Daniel Klein --- docs/configuration.md | 38 +++++++++++++++----------------------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index 5172b73..c3409c7 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -12,7 +12,7 @@ - [3.2.2 oAuth2 Settings](#322-oauth2-settings) - [3.2.3 Bearer Token Settings](#323-bearer-token-settings) - [4. InfluxDB Settings](#4-influxdb-settings) - - [4.1 Influx DB version 1](#41-influx-db-version-1) + - [4.1 InfluxDB version 1](#41-influxdb-version-1) - [4.1 Influx DB version 2](#41-influx-db-version-2) - [πŸ”‘ Additional Passwords](#-additional-passwords) @@ -32,23 +32,15 @@ If this variable is not set, the runtime cannot start correctly. The configuration file is written in JSON format (often stored as .json or .yml) and contains all necessary parameters for connecting the runtime with external services. It is organized into distinct sections, each responsible for a specific system component: +- General Setting +- Asset Connector Settings: Connection settings for the Asset Connector REST API to connect to a MQTT oder OPC UA Broker. +- AAS Server Settings: Connection settings for the AAS Server, including authentication, proxy, TLS/SSL verification, and timeouts. +- InfluxDB Settings (optional): Database connection details for storing time-series data (e.g., host, port, credentials, database name). -AasId: Unique identifier of the Asset Administration Shell (AAS). - -PollingInterval: Interval in seconds for retrieving values from the broker (optional, default: 5). - -AssetConnector: Connection settings for the Asset Connector REST API (e.g., base URL, timeout values, proxy behavior). - -AasServer: Connection settings for the AAS Server, including authentication, proxy, TLS/SSL verification, and timeouts. - -InfluxDb (optional): Database connection details for storing time-series data (e.g., host, port, credentials, database name). - -A detailed overview of the parameters can be found [here](#configuration-parameters). - -A minimal configuration must define at least the AasId, the AssetConnector.base_url, the AasServer.base_url, and the InfluxDb.host/InfluxDb.port. +A minimal configuration must define at least the `AasId`, `the AssetConnector.BaseUrl` and the `AasServer.BaseUrl`. All other parameters are optional and fall back to reasonable defaults. -Example: +Example Structure for AAS Server with oAuth2 authentication and InfluxDB version 1 integration: ```yml { # General Setting @@ -66,13 +58,13 @@ Example: "SslVerify": true, "TrustEnv": true, }, - "InfluxDbVersion": "1", # Set the version of the used Influx DB - "InfluxDb": { # Connection settings for the Influx database (optional) - "Host": "influx_database", # The hostname or IP address of the InfluxDB server (required) - "Port": 8086, # The port number of the InfluxDB server (required) - "Username": "fluid40", # The username for the InfluxDB server (optional, default: "") - "Database": "submodel-db", # The database name to use in InfluxDB (optional, default: "") - "TrustEnv": true, # Disable proxy usage from environment (optional, default: true) + "InfluxDbVersion": "1", # InfluxDB Version Setting + "InfluxDb": { # InfluxDB Settings + "Host": "influx_database", + "Port": 8086, + "Username": "fluid40", + "Database": "submodel-db", + "TrustEnv": true, } } ``` @@ -193,7 +185,7 @@ The InfluxDB integration enables the runtime to store time-series data for later - If the `InfluxDb` node is **not set** in the configuration file, no data will be written to a database. `InfluxDbVersion` - If the `InfluxDb` node is present but the specified database cannot be found or accessed, the runtime will continue operating, but data will not be written to the database. No critical errors will be raised, ensuring robust operation even if the database is temporarily unavailable. -### 4.1 Influx DB version 1 +### 4.1 InfluxDB version 1 | Field | Description | Required | Default | | ------------------------------ | ---------------------------------------------- | -------- | ------- | From ad08d2e4901a40d9dbd50e221b1b47197390c285 Mon Sep 17 00:00:00 2001 From: Daniel Klein Date: Mon, 26 Jan 2026 10:16:32 +0000 Subject: [PATCH 21/28] fix: update AAS Server authentication settings section and improve configuration descriptions Signed-off-by: Daniel Klein --- docs/configuration.md | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index c3409c7..53ef26d 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -6,8 +6,7 @@ - [1. General Settings](#1-general-settings) - [2. Asset Connector Settings](#2-asset-connector-settings) - [3. AAS Server Settings](#3-aas-server-settings) - - [3.1 General Settings](#31-general-settings) - - [3.2 Authentication Settings](#32-authentication-settings) + - [3.1 AAS Server Authentication Settings](#31-aas-server-authentication-settings) - [3.2.1 Basic Authentication Settings](#321-basic-authentication-settings) - [3.2.2 oAuth2 Settings](#322-oauth2-settings) - [3.2.3 Bearer Token Settings](#323-bearer-token-settings) @@ -32,10 +31,10 @@ If this variable is not set, the runtime cannot start correctly. The configuration file is written in JSON format (often stored as .json or .yml) and contains all necessary parameters for connecting the runtime with external services. It is organized into distinct sections, each responsible for a specific system component: -- General Setting -- Asset Connector Settings: Connection settings for the Asset Connector REST API to connect to a MQTT oder OPC UA Broker. -- AAS Server Settings: Connection settings for the AAS Server, including authentication, proxy, TLS/SSL verification, and timeouts. -- InfluxDB Settings (optional): Database connection details for storing time-series data (e.g., host, port, credentials, database name). +- General Setting: Defines the core runtime parameters, such as the AAS identifier and polling interval, required for the application to operate. +- Asset Connector settings: These are the connection settings for the Asset Connector micro service's REST API, which handles the connection to an MQTT or OPC UA broker. +- AAS Server settings: These are the connection settings for the AAS Server, including authentication, proxy, TLS/SSL verification and timeouts. +- InfluxDB Settings (optional): Database connection details for storing time-series data, e.g. host, port, credentials and database name.. A minimal configuration must define at least the `AasId`, `the AssetConnector.BaseUrl` and the `AasServer.BaseUrl`. All other parameters are optional and fall back to reasonable defaults. @@ -57,6 +56,12 @@ Example Structure for AAS Server with oAuth2 authentication and InfluxDB version "ConnectionTimeOut": 100, "SslVerify": true, "TrustEnv": true, + "AuthenticationSettings": { # AAS Server Authentication Settings + "OAuth": { + "ClientId": "my-client-id", + "TokenUrl": "https://auth-server.example.com/oauth/token", + "GrantType": "client_credentials" + } }, "InfluxDbVersion": "1", # InfluxDB Version Setting "InfluxDb": { # InfluxDB Settings @@ -98,8 +103,6 @@ The *Asset Connector Settings* section defines how the runtime communicates with For the connection to the AAS Server the [aas-http-client](https://github.com/fluid40/aas-http-client) package is used. For detailed information about the AAS Server configuration, see the [aas-http-client documentation](https://github.com/fluid40/aas-http-client/blob/main/docs/configuration.md). -### 3.1 General Settings -**Required** | Field | Description | Required | Default | | ------------------------------- | -------------------------------------------- | -------- | ------- | @@ -111,7 +114,7 @@ For detailed information about the AAS Server configuration, see the [aas-http-c | **AasServer.SslVerify** | Verify TLS/SSL certificates. | ❌ No | `true` | | **AasServer.TrustEnv** | Disable proxy usage from environment. | ❌ No | `true` | -### 3.2 Authentication Settings +### 3.1 AAS Server Authentication Settings **Optional** The runtime supports multiple authentication methods for connecting to the AAS Server, allowing secure integration in a variety of environments. Authentication credentials should be provided using environment variables whenever possible to avoid storing sensitive information in configuration files. @@ -132,8 +135,6 @@ The runtime supports multiple authentication methods for connecting to the AAS S Passwords and secrets should be provided via environment variables, not in the configuration file. See the [Additional Passwords](#-additional-passwords) section for details. - - #### 3.2.1 Basic Authentication Settings | Field | Description | Required | Default | From cd2e9df0648eb56b0ac14eda2ec05d59e9cc5665 Mon Sep 17 00:00:00 2001 From: Daniel Klein Date: Mon, 26 Jan 2026 10:25:38 +0000 Subject: [PATCH 22/28] fix: enhance configuration documentation with additional examples for AAS Server and Asset Connector settings Signed-off-by: Daniel Klein --- docs/configuration.md | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/docs/configuration.md b/docs/configuration.md index 53ef26d..761bf5d 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -57,7 +57,7 @@ Example Structure for AAS Server with oAuth2 authentication and InfluxDB version "SslVerify": true, "TrustEnv": true, "AuthenticationSettings": { # AAS Server Authentication Settings - "OAuth": { + "OAuth": { "ClientId": "my-client-id", "TokenUrl": "https://auth-server.example.com/oauth/token", "GrantType": "client_credentials" @@ -84,6 +84,11 @@ The *General Settings* section defines the core parameters required for the runt | **AasId** | Unique identifier of the Asset Administration Shell (AAS). | βœ… Yes | – | | **PollingInterval** | Interval (in seconds) for retrieving values from the broker. | ❌ No | `5` | +Example: +```json +"AasId": "https://fluid40.de/ids/shell/8547_5433_6140_7422", +"PollingInterval": 5 +``` ## 2. Asset Connector Settings **Required** @@ -96,6 +101,16 @@ The *Asset Connector Settings* section defines how the runtime communicates with | **AssetConnector.ConnectionTimeOut** | Connection establishment timeout in seconds. | ❌ No | `100` | | **AssetConnector.TrustEnv** | Disable proxy usage from environment. | ❌ No | `true` | +Example: +```json +"AssetConnector": { + "BaseUrl": "http://mqtt_connector:8000", + "TimeOut": 200, + "ConnectionTimeOut": 100, + "TrustEnv": true, +} +``` + ## 3. AAS Server Settings **Required** @@ -114,6 +129,23 @@ For detailed information about the AAS Server configuration, see the [aas-http-c | **AasServer.SslVerify** | Verify TLS/SSL certificates. | ❌ No | `true` | | **AasServer.TrustEnv** | Disable proxy usage from environment. | ❌ No | `true` | +Example (with Basic Authentication): +Example: +```json +"AasServer": { # AAS Server Settings + "BaseUrl": "http://javaserver:8077/", + "ConnectionTimeOut": 100, + "SslVerify": true, + "TrustEnv": true, + "AuthenticationSettings": { + "BasicAuth": { + "Username": "admin" + } + } +} +``` + + ### 3.1 AAS Server Authentication Settings **Optional** @@ -133,6 +165,8 @@ The runtime supports multiple authentication methods for connecting to the AAS S - No username is required in the configuration. - Provide the token via the `RUNTIME_BEARER_TOKEN` environment variable. +If *Bearer Token* or no authentication is used, the `AuthenticationSettings` node can be omitted. + Passwords and secrets should be provided via environment variables, not in the configuration file. See the [Additional Passwords](#-additional-passwords) section for details. #### 3.2.1 Basic Authentication Settings @@ -176,6 +210,7 @@ Example: #### 3.2.3 Bearer Token Settings Provide the token via the `RUNTIME_BEARER_TOKEN` environment variable. +the `AuthenticationSettings` node can be omitted. ## 4. InfluxDB Settings **Optional** From 81a958093da2f020c47b0a3a0c0cdde7e02a17f7 Mon Sep 17 00:00:00 2001 From: Daniel Klein Date: Mon, 26 Jan 2026 10:35:44 +0000 Subject: [PATCH 23/28] fix: update configuration documentation with improved section headings and additional details on environment variable usage Signed-off-by: Daniel Klein --- docs/configuration.md | 62 ++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index 761bf5d..786daf9 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -3,16 +3,16 @@ - [πŸ› οΈ Configuration](#️-configuration) - [🌐 Overview](#-overview) - [πŸ“‘ Configuration Structure](#-configuration-structure) - - [1. General Settings](#1-general-settings) - - [2. Asset Connector Settings](#2-asset-connector-settings) - - [3. AAS Server Settings](#3-aas-server-settings) - - [3.1 AAS Server Authentication Settings](#31-aas-server-authentication-settings) - - [3.2.1 Basic Authentication Settings](#321-basic-authentication-settings) - - [3.2.2 oAuth2 Settings](#322-oauth2-settings) - - [3.2.3 Bearer Token Settings](#323-bearer-token-settings) - - [4. InfluxDB Settings](#4-influxdb-settings) - - [4.1 InfluxDB version 1](#41-influxdb-version-1) - - [4.1 Influx DB version 2](#41-influx-db-version-2) + - [βš™οΈ General Settings](#️-general-settings) + - [πŸ”— Asset Connector Settings](#-asset-connector-settings) + - [πŸ–₯️ AAS Server Settings](#️-aas-server-settings) + - [πŸ›‘οΈ AAS Server Authentication Settings](#️-aas-server-authentication-settings) + - [πŸ”’ Basic Authentication Settings](#-basic-authentication-settings) + - [πŸ—οΈ oAuth2 Settings](#️-oauth2-settings) + - [πŸͺͺ Bearer Token Settings](#-bearer-token-settings) + - [πŸ“Š InfluxDB Settings](#-influxdb-settings) + - [πŸ“Š1️⃣ InfluxDB version 1 Settings](#1️⃣-influxdb-version-1-settings) + - [πŸ“Š2️⃣ InfluxDB version 2 Settings](#2️⃣-influxdb-version-2-settings) - [πŸ”‘ Additional Passwords](#-additional-passwords) @@ -39,6 +39,8 @@ It is organized into distinct sections, each responsible for a specific system c A minimal configuration must define at least the `AasId`, `the AssetConnector.BaseUrl` and the `AasServer.BaseUrl`. All other parameters are optional and fall back to reasonable defaults. +Passwords and secrets should be provided via environment variables, not in the configuration file. See the [Additional Passwords](#-additional-passwords) section for details. + Example Structure for AAS Server with oAuth2 authentication and InfluxDB version 1 integration: ```yml @@ -74,7 +76,7 @@ Example Structure for AAS Server with oAuth2 authentication and InfluxDB version } ``` -## 1. General Settings +## βš™οΈ General Settings **Required** The *General Settings* section defines the core parameters required for the runtime to operate. These include the unique identifier for the Asset Administration Shell (AAS) and the polling interval for retrieving values from the broker. Proper configuration of these fields ensures the runtime can identify itself and function at the desired update frequency. @@ -89,7 +91,7 @@ Example: "AasId": "https://fluid40.de/ids/shell/8547_5433_6140_7422", "PollingInterval": 5 ``` -## 2. Asset Connector Settings +## πŸ”— Asset Connector Settings **Required** The *Asset Connector Settings* section defines how the runtime communicates with the REST API of the Asset Connector micro service. These parameters specify the API endpoint, timeouts, and proxy handling, ensuring reliable and configurable integration with external asset data sources. @@ -111,9 +113,11 @@ Example: } ``` -## 3. AAS Server Settings +## πŸ–₯️ AAS Server Settings **Required** +The AAS Server Settings section defines how the runtime connects to and interacts with the Asset Administration Shell (AAS) server. These parameters include the server endpoint, timeouts, proxy settings, and SSL verification, ensuring secure and reliable communication with the AAS server for all core operations. + **References:** For the connection to the AAS Server the [aas-http-client](https://github.com/fluid40/aas-http-client) package is used. For detailed information about the AAS Server configuration, see the [aas-http-client documentation](https://github.com/fluid40/aas-http-client/blob/main/docs/configuration.md). @@ -145,8 +149,7 @@ Example: } ``` - -### 3.1 AAS Server Authentication Settings +### πŸ›‘οΈ AAS Server Authentication Settings **Optional** The runtime supports multiple authentication methods for connecting to the AAS Server, allowing secure integration in a variety of environments. Authentication credentials should be provided using environment variables whenever possible to avoid storing sensitive information in configuration files. @@ -169,7 +172,7 @@ If *Bearer Token* or no authentication is used, the `AuthenticationSettings` nod Passwords and secrets should be provided via environment variables, not in the configuration file. See the [Additional Passwords](#-additional-passwords) section for details. -#### 3.2.1 Basic Authentication Settings +#### πŸ”’ Basic Authentication Settings | Field | Description | Required | Default | | ------------------------------------------------------- | --------------------------------------- | -------- | ------- | @@ -186,7 +189,7 @@ Example: } ``` -#### 3.2.2 oAuth2 Settings +#### πŸ—οΈ oAuth2 Settings | Field | Description | Required | Default | | ---------------------------------------------------- | ------------------------------------------------------- | -------- | ---------------------- | @@ -207,21 +210,22 @@ Example: } ``` -#### 3.2.3 Bearer Token Settings +#### πŸͺͺ Bearer Token Settings Provide the token via the `RUNTIME_BEARER_TOKEN` environment variable. the `AuthenticationSettings` node can be omitted. -## 4. InfluxDB Settings +## πŸ“Š InfluxDB Settings **Optional** The InfluxDB integration enables the runtime to store time-series data for later analysis and visualization. This database connection is **optional**. If the `InfluxDb` section is omitted from your configuration file, the runtime will operate normally but will not persist any data to a database. +InfluxDV version 1 and version 2 is supported. **Behavior:** - If the `InfluxDb` node is **not set** in the configuration file, no data will be written to a database. `InfluxDbVersion` - If the `InfluxDb` node is present but the specified database cannot be found or accessed, the runtime will continue operating, but data will not be written to the database. No critical errors will be raised, ensuring robust operation even if the database is temporarily unavailable. -### 4.1 InfluxDB version 1 +### πŸ“Š1️⃣ InfluxDB version 1 Settings | Field | Description | Required | Default | | ------------------------------ | ---------------------------------------------- | -------- | ------- | @@ -233,7 +237,7 @@ The InfluxDB integration enables the runtime to store time-series data for later | **InfluxDb.ConnectionTimeOut** | Connection establishment timeout in seconds. | ❌ No | `100` | | **InfluxDb.TrustEnv** | Disable proxy usage from environment. | ❌ No | `true` | -Passwords and secrets should be provided via environment variables, not in the configuration file. See the [Additional Passwords](#-additional-passwords) section for details. +Provide the database password via the `RUNTIME_INFLUX_PW` environment variable. Example: ```json @@ -248,7 +252,7 @@ Example: } ``` -### 4.1 Influx DB version 2 +### πŸ“Š2️⃣ InfluxDB version 2 Settings | Field | Description | Required | Default | | ------------------------------ | ---------------------------------------------- | -------- | ------- | @@ -260,6 +264,8 @@ Example: | **InfluxDb.ConnectionTimeOut** | Connection establishment timeout in seconds. | ❌ No | `100` | | **InfluxDb.TrustEnv** | Disable proxy usage from environment. | ❌ No | `true` | +Provide the database token via the `RUNTIME_INFLUX_PW` environment variable. + Example: ```json "InfluxDbVersion": "2", @@ -275,12 +281,12 @@ Example: Some components may require authentication. Instead of storing sensitive information in the configuration file, passwords must be provided via environment variables: -| Component | Environment Variable | Description | -| ---------- | ----------------------- | --------------------------------------------------------------- | -| AAS Server | `RUNTIME_BASIC_AUTH_PW` | Password used to authenticate with the AAS Server by basic auth | -| AAS Server | `RUNTIME_OAUTH_SECRET` | Secret used to authenticate with the AAS Server by oAuth | -| AAS Server | `RUNTIME_BEARER_TOKEN` | Bearer Token used to authenticate with the AAS Server by Token | -| InfluxDB | `RUNTIME_INFLUX_PW` | Password used to authenticate with the InfluxDB | +| Component | Environment Variable | Description | +| ---------- | ----------------------- | ------------------------------------------------------------------ | +| AAS Server | `RUNTIME_BASIC_AUTH_PW` | Password used to authenticate with the AAS Server by basic auth | +| AAS Server | `RUNTIME_OAUTH_SECRET` | Secret used to authenticate with the AAS Server by oAuth | +| AAS Server | `RUNTIME_BEARER_TOKEN` | Bearer Token used to authenticate with the AAS Server by Token | +| InfluxDB | `RUNTIME_INFLUX_PW` | Password (v1) or token (v2) used to authenticate with the InfluxDB | This approach keeps credentials secure and ensures they can be easily managed across different environments (development, staging, production). From 46eb609d67c24264fe9aa63151e0071a0ad5bfac Mon Sep 17 00:00:00 2001 From: Daniel Klein Date: Mon, 26 Jan 2026 10:43:05 +0000 Subject: [PATCH 24/28] fix: add additional AAS Server configuration parameters for proxy settings and timeout Signed-off-by: Daniel Klein --- docs/configuration.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/configuration.md b/docs/configuration.md index 786daf9..1bfa51f 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -136,8 +136,11 @@ For detailed information about the AAS Server configuration, see the [aas-http-c Example (with Basic Authentication): Example: ```json -"AasServer": { # AAS Server Settings +"AasServer": { "BaseUrl": "http://javaserver:8077/", + "HttpsProxy": "", + "HttpProxy": "", + "TimeOut": 200, "ConnectionTimeOut": 100, "SslVerify": true, "TrustEnv": true, From 08718ba962c3e72ab71fc13a7294c471cbdb54d0 Mon Sep 17 00:00:00 2001 From: Daniel Klein Date: Mon, 26 Jan 2026 10:53:34 +0000 Subject: [PATCH 25/28] fix: update InfluxDB configuration details and clarify version requirements Signed-off-by: Daniel Klein --- docs/configuration.md | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index 1bfa51f..fd2793a 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -222,12 +222,15 @@ the `AuthenticationSettings` node can be omitted. **Optional** The InfluxDB integration enables the runtime to store time-series data for later analysis and visualization. This database connection is **optional**. If the `InfluxDb` section is omitted from your configuration file, the runtime will operate normally but will not persist any data to a database. -InfluxDV version 1 and version 2 is supported. **Behavior:** - If the `InfluxDb` node is **not set** in the configuration file, no data will be written to a database. `InfluxDbVersion` - If the `InfluxDb` node is present but the specified database cannot be found or accessed, the runtime will continue operating, but data will not be written to the database. No critical errors will be raised, ensuring robust operation even if the database is temporarily unavailable. +InfluxDB version 1 and version 2 is supported. Set 'InfluxDbVersion' to: +- `1` for InfluxDB version 1 +- `2` for InfluxDB version 2 + ### πŸ“Š1️⃣ InfluxDB version 1 Settings | Field | Description | Required | Default | @@ -240,6 +243,7 @@ InfluxDV version 1 and version 2 is supported. | **InfluxDb.ConnectionTimeOut** | Connection establishment timeout in seconds. | ❌ No | `100` | | **InfluxDb.TrustEnv** | Disable proxy usage from environment. | ❌ No | `true` | +The property 'InfluxDbVersion' must be set to the value 1. Provide the database password via the `RUNTIME_INFLUX_PW` environment variable. Example: @@ -257,16 +261,15 @@ Example: ### πŸ“Š2️⃣ InfluxDB version 2 Settings -| Field | Description | Required | Default | -| ------------------------------ | ---------------------------------------------- | -------- | ------- | -| **InfluxDbVersion** | Set the version of the Influx DB | βœ… Yes | - | -| **InfluxDb.Host** | Hostname or IP address of the InfluxDB server. | βœ… Yes | – | -| **InfluxDb.Port** | Port number of the InfluxDB server. | βœ… Yes | – | -| **InfluxDb.Username** | Username for the InfluxDB server. | ❌ No | `""` | -| **InfluxDb.Database** | Database name to use in InfluxDB. | ❌ No | `""` | -| **InfluxDb.ConnectionTimeOut** | Connection establishment timeout in seconds. | ❌ No | `100` | -| **InfluxDb.TrustEnv** | Disable proxy usage from environment. | ❌ No | `true` | +| Field | Description | Required | Default | +| ------------------------------ | -------------------------------------------- | -------- | ------- | +| **InfluxDbVersion** | Set the version of the Influx DB | βœ… Yes | - | +| **InfluxDb.Url** | URL of the InfluxDB server. | βœ… Yes | – | +| **InfluxDb.Organization** | Organization name to use in InfluxDB. | βœ… Yes | – | +| **InfluxDb.Bucket** | Bucket name to use in InfluxDB. | βœ… Yes | - | +| **InfluxDb.ConnectionTimeOut** | Connection establishment timeout in seconds. | ❌ No | `100` | +The property 'InfluxDbVersion' must be set to the value 2. Provide the database token via the `RUNTIME_INFLUX_PW` environment variable. Example: @@ -274,7 +277,7 @@ Example: "InfluxDbVersion": "2", "InfluxDb": { "Url": "http://influx_database_v2-rt:8086/", - "Organization": "fluid40", + "Organization": "fluid40-org", "Bucket": "submodel-db", "ConnectionTimeOut": 60 } From 00148dcdb51e6bb9267e35ac357ce201b7595f8d Mon Sep 17 00:00:00 2001 From: Daniel Klein Date: Mon, 26 Jan 2026 11:17:27 +0000 Subject: [PATCH 26/28] fix: update AAS Server authentication settings to mark required fields and clarify defaults Signed-off-by: Daniel Klein --- docs/configuration.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index fd2793a..6cbc74c 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -179,7 +179,7 @@ Passwords and secrets should be provided via environment variables, not in the c | Field | Description | Required | Default | | ------------------------------------------------------- | --------------------------------------- | -------- | ------- | -| **AasServer.AuthenticationSettings.BasicAuth.Username** | Username for HTTP Basic Authentication. | ❌ No | `""` | +| **AasServer.AuthenticationSettings.BasicAuth.Username** | Username for HTTP Basic Authentication. | βœ… Yes | - | Provide the password via the `RUNTIME_BASIC_AUTH_PW` environment variable. @@ -196,8 +196,8 @@ Example: | Field | Description | Required | Default | | ---------------------------------------------------- | ------------------------------------------------------- | -------- | ---------------------- | -| **AasServer.AuthenticationSettings.OAuth.ClientId** | OAuth2 client identifier. | ❌ No | `""` | -| **AasServer.AuthenticationSettings.OAuth.TokenUrl** | OAuth2 token endpoint URL. | ❌ No | `""` | +| **AasServer.AuthenticationSettings.OAuth.ClientId** | OAuth2 client identifier. | βœ… Yes | - | +| **AasServer.AuthenticationSettings.OAuth.TokenUrl** | OAuth2 token endpoint URL. | βœ… Yes | - | | **AasServer.AuthenticationSettings.OAuth.GrantType** | OAuth2 grant type (`client_credentials` or `password`). | ❌ No | `"client_credentials"` | Provide the client secret via the `RUNTIME_OAUTH_SECRET` environment variable. @@ -216,7 +216,7 @@ Example: #### πŸͺͺ Bearer Token Settings Provide the token via the `RUNTIME_BEARER_TOKEN` environment variable. -the `AuthenticationSettings` node can be omitted. +The `AuthenticationSettings` node can be omitted. ## πŸ“Š InfluxDB Settings **Optional** From cfa98da5c4cdae2c8617f3f067f215a739fa0ef0 Mon Sep 17 00:00:00 2001 From: Daniel Klein Date: Mon, 26 Jan 2026 11:18:58 +0000 Subject: [PATCH 27/28] fix: update configuration documentation with improved section headings for clarity and structure Signed-off-by: Daniel Klein --- docs/configuration.md | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index 6cbc74c..67dfb35 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -3,16 +3,16 @@ - [πŸ› οΈ Configuration](#️-configuration) - [🌐 Overview](#-overview) - [πŸ“‘ Configuration Structure](#-configuration-structure) - - [βš™οΈ General Settings](#️-general-settings) - - [πŸ”— Asset Connector Settings](#-asset-connector-settings) - - [πŸ–₯️ AAS Server Settings](#️-aas-server-settings) - - [πŸ›‘οΈ AAS Server Authentication Settings](#️-aas-server-authentication-settings) - - [πŸ”’ Basic Authentication Settings](#-basic-authentication-settings) - - [πŸ—οΈ oAuth2 Settings](#️-oauth2-settings) - - [πŸͺͺ Bearer Token Settings](#-bearer-token-settings) - - [πŸ“Š InfluxDB Settings](#-influxdb-settings) - - [πŸ“Š1️⃣ InfluxDB version 1 Settings](#1️⃣-influxdb-version-1-settings) - - [πŸ“Š2️⃣ InfluxDB version 2 Settings](#2️⃣-influxdb-version-2-settings) + - [βš™οΈ General Settings](#️-general-settings) + - [πŸ”— Asset Connector Settings](#-asset-connector-settings) + - [πŸ–₯️ AAS Server Settings](#️-aas-server-settings) + - [πŸ›‘οΈ AAS Server Authentication Settings](#️-aas-server-authentication-settings) + - [πŸ”’ Basic Authentication Settings](#-basic-authentication-settings) + - [πŸ—οΈ oAuth2 Settings](#️-oauth2-settings) + - [πŸͺͺ Bearer Token Settings](#-bearer-token-settings) + - [πŸ“Š InfluxDB Settings](#-influxdb-settings) + - [πŸ“Š1️⃣ InfluxDB version 1 Settings](#1️⃣-influxdb-version-1-settings) + - [πŸ“Š2️⃣ InfluxDB version 2 Settings](#2️⃣-influxdb-version-2-settings) - [πŸ”‘ Additional Passwords](#-additional-passwords) @@ -76,7 +76,7 @@ Example Structure for AAS Server with oAuth2 authentication and InfluxDB version } ``` -## βš™οΈ General Settings +### βš™οΈ General Settings **Required** The *General Settings* section defines the core parameters required for the runtime to operate. These include the unique identifier for the Asset Administration Shell (AAS) and the polling interval for retrieving values from the broker. Proper configuration of these fields ensures the runtime can identify itself and function at the desired update frequency. @@ -91,7 +91,7 @@ Example: "AasId": "https://fluid40.de/ids/shell/8547_5433_6140_7422", "PollingInterval": 5 ``` -## πŸ”— Asset Connector Settings +### πŸ”— Asset Connector Settings **Required** The *Asset Connector Settings* section defines how the runtime communicates with the REST API of the Asset Connector micro service. These parameters specify the API endpoint, timeouts, and proxy handling, ensuring reliable and configurable integration with external asset data sources. @@ -113,7 +113,7 @@ Example: } ``` -## πŸ–₯️ AAS Server Settings +### πŸ–₯️ AAS Server Settings **Required** The AAS Server Settings section defines how the runtime connects to and interacts with the Asset Administration Shell (AAS) server. These parameters include the server endpoint, timeouts, proxy settings, and SSL verification, ensuring secure and reliable communication with the AAS server for all core operations. @@ -152,7 +152,7 @@ Example: } ``` -### πŸ›‘οΈ AAS Server Authentication Settings +#### πŸ›‘οΈ AAS Server Authentication Settings **Optional** The runtime supports multiple authentication methods for connecting to the AAS Server, allowing secure integration in a variety of environments. Authentication credentials should be provided using environment variables whenever possible to avoid storing sensitive information in configuration files. @@ -175,7 +175,7 @@ If *Bearer Token* or no authentication is used, the `AuthenticationSettings` nod Passwords and secrets should be provided via environment variables, not in the configuration file. See the [Additional Passwords](#-additional-passwords) section for details. -#### πŸ”’ Basic Authentication Settings +##### πŸ”’ Basic Authentication Settings | Field | Description | Required | Default | | ------------------------------------------------------- | --------------------------------------- | -------- | ------- | @@ -192,7 +192,7 @@ Example: } ``` -#### πŸ—οΈ oAuth2 Settings +##### πŸ—οΈ oAuth2 Settings | Field | Description | Required | Default | | ---------------------------------------------------- | ------------------------------------------------------- | -------- | ---------------------- | @@ -213,12 +213,12 @@ Example: } ``` -#### πŸͺͺ Bearer Token Settings +##### πŸͺͺ Bearer Token Settings Provide the token via the `RUNTIME_BEARER_TOKEN` environment variable. The `AuthenticationSettings` node can be omitted. -## πŸ“Š InfluxDB Settings +### πŸ“Š InfluxDB Settings **Optional** The InfluxDB integration enables the runtime to store time-series data for later analysis and visualization. This database connection is **optional**. If the `InfluxDb` section is omitted from your configuration file, the runtime will operate normally but will not persist any data to a database. @@ -231,7 +231,7 @@ InfluxDB version 1 and version 2 is supported. Set 'InfluxDbVersion' to: - `1` for InfluxDB version 1 - `2` for InfluxDB version 2 -### πŸ“Š1️⃣ InfluxDB version 1 Settings +#### πŸ“Š1️⃣ InfluxDB version 1 Settings | Field | Description | Required | Default | | ------------------------------ | ---------------------------------------------- | -------- | ------- | @@ -259,7 +259,7 @@ Example: } ``` -### πŸ“Š2️⃣ InfluxDB version 2 Settings +#### πŸ“Š2️⃣ InfluxDB version 2 Settings | Field | Description | Required | Default | | ------------------------------ | -------------------------------------------- | -------- | ------- | From 34d1cf0ad6a9e52fdbaf65226107cb9c580870ff Mon Sep 17 00:00:00 2001 From: Daniel Klein Date: Mon, 26 Jan 2026 11:20:42 +0000 Subject: [PATCH 28/28] fix: update changelog to include WIP documentation rework Signed-off-by: Daniel Klein --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75eb8de..18893df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,3 +4,4 @@ - ✨Feature: Ass support for InfluxDB database version 2 - πŸš€Improvement: Improve structure of data written to database - πŸš€Improvement: Standardization of configuration property names (see [configuration](docs/configuration.md)) +- πŸ“„Documentation: Re-Work documentation (WIP)