aas-http-client 0.2.6__py3-none-any.whl → 0.2.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of aas-http-client might be problematic. Click here for more details.
- aas_http_client/client.py +41 -8
- aas_http_client/demo/demo_process.py +43 -41
- aas_http_client/utilities/model_builder.py +18 -24
- aas_http_client/wrapper/sdk_wrapper.py +59 -38
- {aas_http_client-0.2.6.dist-info → aas_http_client-0.2.8.dist-info}/METADATA +1 -1
- aas_http_client-0.2.8.dist-info/RECORD +14 -0
- aas_http_client-0.2.6.dist-info/RECORD +0 -14
- {aas_http_client-0.2.6.dist-info → aas_http_client-0.2.8.dist-info}/WHEEL +0 -0
- {aas_http_client-0.2.6.dist-info → aas_http_client-0.2.8.dist-info}/licenses/LICENSE +0 -0
- {aas_http_client-0.2.6.dist-info → aas_http_client-0.2.8.dist-info}/top_level.txt +0 -0
aas_http_client/client.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"""Client for HTTP API communication with AAS server."""
|
|
2
|
+
|
|
2
3
|
import json
|
|
3
4
|
import logging
|
|
4
5
|
import time
|
|
@@ -8,12 +9,13 @@ import basyx.aas.adapter.json
|
|
|
8
9
|
import basyx.aas.adapter.json.json_serialization as js
|
|
9
10
|
import requests
|
|
10
11
|
from basyx.aas.model import Reference, Submodel
|
|
11
|
-
from aas_http_client.core.encoder import decode_base_64
|
|
12
12
|
from pydantic import BaseModel, PrivateAttr, ValidationError
|
|
13
13
|
from requests import Session
|
|
14
14
|
from requests.auth import HTTPBasicAuth
|
|
15
15
|
from requests.models import Response
|
|
16
16
|
|
|
17
|
+
from aas_http_client.core.encoder import decode_base_64
|
|
18
|
+
|
|
17
19
|
logger = logging.getLogger(__name__)
|
|
18
20
|
|
|
19
21
|
STATUS_CODE_200 = 200
|
|
@@ -55,7 +57,7 @@ def log_response_errors(response: Response):
|
|
|
55
57
|
result_error_messages.append(str(message))
|
|
56
58
|
elif "error" in response_content_dict:
|
|
57
59
|
result_error_messages.append(response_content_dict.get("error", ""))
|
|
58
|
-
|
|
60
|
+
|
|
59
61
|
if len(result_error_messages) == 0 and response.text:
|
|
60
62
|
result_error_messages.append(response.text)
|
|
61
63
|
|
|
@@ -121,7 +123,7 @@ class AasHttpClient(BaseModel):
|
|
|
121
123
|
content = response.content.decode("utf-8")
|
|
122
124
|
return json.loads(content)
|
|
123
125
|
|
|
124
|
-
# region shells
|
|
126
|
+
# region shells
|
|
125
127
|
|
|
126
128
|
def post_asset_administration_shell(self, aas_data: dict) -> dict | None:
|
|
127
129
|
"""Creates a new Asset Administration Shell.
|
|
@@ -242,7 +244,6 @@ class AasHttpClient(BaseModel):
|
|
|
242
244
|
content = response.content.decode("utf-8")
|
|
243
245
|
return json.loads(content)
|
|
244
246
|
|
|
245
|
-
|
|
246
247
|
def get_asset_administration_shell_by_id_reference_aas_repository(self, aas_id: str) -> Reference | None:
|
|
247
248
|
"""Returns a specific Asset Administration Shell as a Reference.
|
|
248
249
|
|
|
@@ -278,7 +279,7 @@ class AasHttpClient(BaseModel):
|
|
|
278
279
|
decoded_submodel_id: str = decode_base_64(submodel_id)
|
|
279
280
|
|
|
280
281
|
url = f"{self.base_url}/shells/{decoded_aas_id}/submodels/{decoded_submodel_id}"
|
|
281
|
-
|
|
282
|
+
# /shells/{aasIdentifier}/submodels/{submodelIdentifier}
|
|
282
283
|
|
|
283
284
|
try:
|
|
284
285
|
response = self._session.get(url, headers=HEADERS, timeout=self.time_out)
|
|
@@ -318,9 +319,9 @@ class AasHttpClient(BaseModel):
|
|
|
318
319
|
|
|
319
320
|
return True
|
|
320
321
|
|
|
321
|
-
# endregion
|
|
322
|
+
# endregion
|
|
322
323
|
|
|
323
|
-
# region submodels
|
|
324
|
+
# region submodels
|
|
324
325
|
|
|
325
326
|
def post_submodel(self, submodel_data: dict) -> dict | None:
|
|
326
327
|
"""Creates a new Submodel.
|
|
@@ -509,10 +510,38 @@ class AasHttpClient(BaseModel):
|
|
|
509
510
|
content = response.content.decode("utf-8")
|
|
510
511
|
return json.loads(content)
|
|
511
512
|
|
|
513
|
+
def get_submodel_element_by_path_submodel_repo(self, submodel_id: str, submodel_element_path: str) -> dict | None:
|
|
514
|
+
"""Returns a specific submodel element from the Submodel at a specified path.
|
|
515
|
+
|
|
516
|
+
:param submodel_id: Encoded ID of the Submodel to retrieve element from
|
|
517
|
+
:param submodel_element_path: Path of the Submodel element to retrieve
|
|
518
|
+
:return: Submodel element data or None if an error occurred
|
|
519
|
+
"""
|
|
520
|
+
decoded_submodel_id: str = decode_base_64(submodel_id)
|
|
521
|
+
|
|
522
|
+
url = f"{self.base_url}/submodels/{decoded_submodel_id}/submodel-elements/{submodel_element_path}"
|
|
523
|
+
|
|
524
|
+
try:
|
|
525
|
+
response = self._session.get(url, headers=HEADERS, timeout=self.time_out)
|
|
526
|
+
logger.debug(f"Call REST API url '{response.url}'")
|
|
527
|
+
|
|
528
|
+
if response.status_code != STATUS_CODE_200:
|
|
529
|
+
log_response_errors(response)
|
|
530
|
+
return None
|
|
531
|
+
|
|
532
|
+
except requests.exceptions.RequestException as e:
|
|
533
|
+
logger.error(f"Error call REST API: {e}")
|
|
534
|
+
return None
|
|
535
|
+
|
|
536
|
+
content = response.content.decode("utf-8")
|
|
537
|
+
return json.loads(content)
|
|
538
|
+
|
|
539
|
+
|
|
512
540
|
# endregion
|
|
513
541
|
|
|
514
542
|
# region client
|
|
515
543
|
|
|
544
|
+
|
|
516
545
|
def create_client_by_url(
|
|
517
546
|
base_url: str,
|
|
518
547
|
username: str = "",
|
|
@@ -547,6 +576,7 @@ def create_client_by_url(
|
|
|
547
576
|
config_string = json.dumps(config_dict, indent=4)
|
|
548
577
|
return _create_client(config_string, password)
|
|
549
578
|
|
|
579
|
+
|
|
550
580
|
def create_client_by_config(config_file: Path, password: str = "") -> AasHttpClient | None:
|
|
551
581
|
"""Create a AAS HTTP client from the given parameters.
|
|
552
582
|
|
|
@@ -565,6 +595,7 @@ def create_client_by_config(config_file: Path, password: str = "") -> AasHttpCli
|
|
|
565
595
|
|
|
566
596
|
return _create_client(config_string, password)
|
|
567
597
|
|
|
598
|
+
|
|
568
599
|
def _create_client(config_string: str, password) -> AasHttpClient | None:
|
|
569
600
|
try:
|
|
570
601
|
connection_settings = AasHttpClient.model_validate_json(config_string)
|
|
@@ -590,6 +621,7 @@ def _create_client(config_string: str, password) -> AasHttpClient | None:
|
|
|
590
621
|
|
|
591
622
|
return client
|
|
592
623
|
|
|
624
|
+
|
|
593
625
|
def _connect_to_api(client: AasHttpClient) -> bool:
|
|
594
626
|
start_time = time.time()
|
|
595
627
|
logger.debug(f"Try to connect to REST API '{client.base_url}' for {client.connection_time_out} seconds")
|
|
@@ -609,4 +641,5 @@ def _connect_to_api(client: AasHttpClient) -> bool:
|
|
|
609
641
|
logger.warning(f"Retrying connection (attempt: {counter})")
|
|
610
642
|
time.sleep(1)
|
|
611
643
|
|
|
612
|
-
|
|
644
|
+
|
|
645
|
+
# endregion
|
|
@@ -1,93 +1,95 @@
|
|
|
1
|
+
"""Main process for the demo."""
|
|
2
|
+
|
|
1
3
|
import logging
|
|
2
|
-
import aas_http_client.utilities.model_builder as model_builder
|
|
3
|
-
from aas_http_client.client import create_client_by_config, AasHttpClient
|
|
4
|
-
from aas_http_client.wrapper.sdk_wrapper import SdkWrapper, create_wrapper_by_config
|
|
5
4
|
from pathlib import Path
|
|
6
|
-
import json
|
|
7
|
-
import basyx.aas.adapter.json
|
|
8
|
-
import basyx.aas.model
|
|
9
5
|
|
|
10
6
|
from basyx.aas import model
|
|
11
7
|
|
|
8
|
+
from aas_http_client.client import AasHttpClient, create_client_by_config
|
|
9
|
+
from aas_http_client.utilities import model_builder
|
|
10
|
+
from aas_http_client.wrapper.sdk_wrapper import SdkWrapper, create_wrapper_by_config
|
|
11
|
+
|
|
12
12
|
logger = logging.getLogger(__name__)
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
|
|
15
|
+
def start() -> None:
|
|
15
16
|
"""Start the demo process."""
|
|
16
17
|
# create a submodel element
|
|
17
18
|
sme_short_id: str = model_builder.create_unique_short_id("poc_sme")
|
|
18
19
|
sme = model_builder.create_base_submodel_element_Property(sme_short_id, model.datatypes.String, "Sample Value")
|
|
19
|
-
|
|
20
|
+
|
|
20
21
|
# create a submodel
|
|
21
22
|
sm_short_id: str = model_builder.create_unique_short_id("poc_sm")
|
|
22
23
|
submodel = model_builder.create_base_submodel(sm_short_id)
|
|
23
24
|
# add submodel element to submodel
|
|
24
25
|
# submodel.submodel_element.add(sme)
|
|
25
|
-
|
|
26
|
+
|
|
26
27
|
# create an AAS
|
|
27
28
|
aas_short_id: str = model_builder.create_unique_short_id("poc_aas")
|
|
28
29
|
aas = model_builder.create_base_ass(aas_short_id)
|
|
29
|
-
|
|
30
|
+
|
|
30
31
|
# add submodel to AAS
|
|
31
32
|
model_builder.add_submodel_to_aas(aas, submodel)
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
|
|
34
|
+
wrapper = _create_sdk_wrapper(Path("./aas_http_client/demo/python_server_config.json"))
|
|
34
35
|
# dotnet_sdk_wrapper = _create_sdk_wrapper(Path("./aas_http_client/demo/dotnet_server_config.json"))
|
|
35
36
|
|
|
36
|
-
for existing_shell in
|
|
37
|
+
for existing_shell in wrapper.get_all_asset_administration_shells():
|
|
37
38
|
logger.warning(f"Delete shell '{existing_shell.id}'")
|
|
38
|
-
|
|
39
|
+
wrapper.delete_asset_administration_shell_by_id(existing_shell.id)
|
|
39
40
|
|
|
40
|
-
for existing_submodel in
|
|
41
|
+
for existing_submodel in wrapper.get_all_submodels():
|
|
41
42
|
logger.warning(f"Delete submodel '{existing_submodel.id}'")
|
|
42
|
-
|
|
43
|
+
wrapper.delete_submodel_by_id(existing_submodel.id)
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
wrapper.post_asset_administration_shell(aas)
|
|
46
|
+
wrapper.post_submodel(submodel)
|
|
46
47
|
|
|
47
|
-
tmp =
|
|
48
|
+
tmp = wrapper.get_asset_administration_shell_by_id_reference_aas_repository(aas.id)
|
|
48
49
|
|
|
49
|
-
shell =
|
|
50
|
-
submodel =
|
|
50
|
+
shell = wrapper.get_asset_administration_shell_by_id(aas.id)
|
|
51
|
+
submodel = wrapper.get_submodel_by_id(submodel.id)
|
|
51
52
|
|
|
52
|
-
|
|
53
|
+
wrapper.post_submodel_element_submodel_repo(submodel.id, sme)
|
|
53
54
|
|
|
54
|
-
submodel =
|
|
55
|
-
|
|
55
|
+
submodel = wrapper.get_submodel_by_id(submodel.id)
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
aas = model_builder.create_base_ass(aas_short_id)
|
|
57
|
+
for existing_shell in wrapper.get_all_asset_administration_shells():
|
|
58
|
+
logger.warning(f"Delete shell '{existing_shell.id}'")
|
|
59
|
+
wrapper.delete_asset_administration_shell_by_id(existing_shell.id)
|
|
61
60
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
61
|
+
for existing_submodel in wrapper.get_all_submodels():
|
|
62
|
+
logger.warning(f"Delete submodel '{existing_submodel.id}'")
|
|
63
|
+
wrapper.delete_submodel_by_id(existing_submodel.id)
|
|
65
64
|
|
|
66
|
-
# add Submodel to AAS
|
|
67
|
-
model_builder.add_submodel_to_aas(aas, submodel)
|
|
68
|
-
|
|
69
|
-
return aas
|
|
70
65
|
|
|
71
66
|
def _create_client(config: Path) -> AasHttpClient:
|
|
72
|
-
"""Create client
|
|
67
|
+
"""Create a HTTP client from a given configuration file.
|
|
73
68
|
|
|
69
|
+
:param config: Given configuration file
|
|
70
|
+
:return: HTTP client
|
|
71
|
+
"""
|
|
74
72
|
try:
|
|
75
73
|
file = config
|
|
76
74
|
client = create_client_by_config(file, password="")
|
|
75
|
+
|
|
77
76
|
except Exception as e:
|
|
78
77
|
logger.error(f"Failed to create client for {file}: {e}")
|
|
79
|
-
pass
|
|
80
78
|
|
|
81
79
|
return client
|
|
82
|
-
|
|
80
|
+
|
|
81
|
+
|
|
83
82
|
def _create_sdk_wrapper(config: Path) -> SdkWrapper:
|
|
84
|
-
"""Create
|
|
83
|
+
"""Create a SDK wrapper from a given configuration file.
|
|
85
84
|
|
|
85
|
+
:param config: Given configuration file
|
|
86
|
+
:return: SDK wrapper
|
|
87
|
+
"""
|
|
86
88
|
try:
|
|
87
89
|
file = config
|
|
88
90
|
client = create_wrapper_by_config(file, password="")
|
|
91
|
+
|
|
89
92
|
except Exception as e:
|
|
90
93
|
logger.error(f"Failed to create client for {file}: {e}")
|
|
91
|
-
pass
|
|
92
94
|
|
|
93
|
-
return client
|
|
95
|
+
return client
|
|
@@ -4,9 +4,10 @@ Provides some helper methods for easier work with basyx sdk data model
|
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
import uuid
|
|
7
|
+
from typing import Any
|
|
7
8
|
|
|
8
9
|
from basyx.aas import model
|
|
9
|
-
|
|
10
|
+
|
|
10
11
|
|
|
11
12
|
def create_unique_short_id(id_short: str) -> str:
|
|
12
13
|
"""Generate a unique identifier string by appending a UUID to the provided ID short.
|
|
@@ -16,41 +17,39 @@ def create_unique_short_id(id_short: str) -> str:
|
|
|
16
17
|
"""
|
|
17
18
|
return f"{id_short}_{str(uuid.uuid4()).replace('-', '_')}"
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
|
|
21
|
+
def create_base_submodel_element_Property(
|
|
22
|
+
id_short: str, type: model.datatypes, value: Any, display_name: str = "", description: str = ""
|
|
23
|
+
) -> model.Property:
|
|
24
|
+
"""Create a basic Property Submodel Element."""
|
|
25
|
+
sme = model.Property(id_short=id_short, value_type=type, value=value)
|
|
26
|
+
|
|
27
27
|
if not description:
|
|
28
28
|
description = f"This is the submodel element with ID short '{id_short}'"
|
|
29
29
|
|
|
30
30
|
description_text = {"en": f"{description}"}
|
|
31
31
|
sme.description = model.MultiLanguageTextType(description_text)
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
if not display_name:
|
|
34
34
|
display_name = "POC Submodel Element"
|
|
35
35
|
|
|
36
36
|
display_name_text = {"en": f"{display_name}"}
|
|
37
37
|
sme.display_name = model.MultiLanguageTextType(display_name_text)
|
|
38
|
-
|
|
38
|
+
|
|
39
39
|
return sme
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
|
|
42
|
+
def create_base_submodel(id_short: str, namespace: str = "fluid40", display_name: str = "", description: str = "") -> model.Submodel:
|
|
42
43
|
"""Create a basic Submodel.
|
|
43
44
|
|
|
44
45
|
:param id_short: ID short of the Submodel
|
|
45
|
-
:param namespace: namespace of the Submodel , defaults to "
|
|
46
|
+
:param namespace: namespace of the Submodel , defaults to "fluid40"
|
|
46
47
|
:param display_name: display name of the Submodel, defaults to ""
|
|
47
48
|
:param description: description of the Submodel, defaults to ""
|
|
48
49
|
:return: Submodel instance
|
|
49
50
|
"""
|
|
50
|
-
if namespace
|
|
51
|
-
|
|
52
|
-
else:
|
|
53
|
-
identifier = id_short
|
|
51
|
+
identifier = f"{namespace}/{id_short}" if namespace else id_short
|
|
52
|
+
|
|
54
53
|
sm = model.Submodel(identifier)
|
|
55
54
|
sm.id_short = id_short
|
|
56
55
|
|
|
@@ -69,9 +68,7 @@ def create_base_submodel(id_short: str, namespace: str = "basyx_python_aas_serve
|
|
|
69
68
|
return sm
|
|
70
69
|
|
|
71
70
|
|
|
72
|
-
def create_base_ass(
|
|
73
|
-
id_short: str, namespace: str = "basyx_python_aas_server", display_name: str = "", description: str = ""
|
|
74
|
-
) -> model.AssetAdministrationShell:
|
|
71
|
+
def create_base_ass(id_short: str, namespace: str = "fluid40", display_name: str = "", description: str = "") -> model.AssetAdministrationShell:
|
|
75
72
|
"""Create a basic AAS.
|
|
76
73
|
|
|
77
74
|
:param id_short: ID short of the AAS
|
|
@@ -117,10 +114,7 @@ def create_base_asset_information(id_short: str, namespace: str = "basyx_python_
|
|
|
117
114
|
:param namespace: namespace of the AssetInformation, defaults to "basyx_python_aas_server"
|
|
118
115
|
:return: AssetInformation instance
|
|
119
116
|
"""
|
|
120
|
-
if namespace
|
|
121
|
-
identifier = f"{namespace}/{id_short}"
|
|
122
|
-
else:
|
|
123
|
-
identifier = id_short
|
|
117
|
+
identifier = f"{namespace}/{id_short}" if namespace else id_short
|
|
124
118
|
return model.AssetInformation(model.AssetKind.INSTANCE, identifier)
|
|
125
119
|
|
|
126
120
|
|
|
@@ -6,17 +6,20 @@ from pathlib import Path
|
|
|
6
6
|
from typing import Any
|
|
7
7
|
|
|
8
8
|
import basyx.aas.adapter.json
|
|
9
|
-
|
|
10
9
|
from basyx.aas import model
|
|
10
|
+
|
|
11
11
|
from aas_http_client.client import AasHttpClient, _create_client
|
|
12
|
+
|
|
12
13
|
logger = logging.getLogger(__name__)
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
|
|
16
|
+
class SdkWrapper:
|
|
15
17
|
"""Represents a wrapper for the BaSyx Python SDK to communicate with a REST API."""
|
|
16
|
-
_client: AasHttpClient = None
|
|
17
|
-
base_url: str = ""
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
_client: AasHttpClient = None
|
|
20
|
+
base_url: str = ""
|
|
21
|
+
|
|
22
|
+
# region shells
|
|
20
23
|
|
|
21
24
|
def post_asset_administration_shell(self, aas: model.AssetAdministrationShell) -> model.AssetAdministrationShell | None:
|
|
22
25
|
"""Creates a new Asset Administration Shell.
|
|
@@ -54,7 +57,7 @@ class SdkWrapper():
|
|
|
54
57
|
:return: Asset Administration Shells objects or None if an error occurred
|
|
55
58
|
"""
|
|
56
59
|
content: dict = self._client.get_all_asset_administration_shells()
|
|
57
|
-
|
|
60
|
+
|
|
58
61
|
if not content:
|
|
59
62
|
return None
|
|
60
63
|
|
|
@@ -79,16 +82,16 @@ class SdkWrapper():
|
|
|
79
82
|
|
|
80
83
|
def get_asset_administration_shell_by_id(self, aas_id: str) -> model.AssetAdministrationShell | None:
|
|
81
84
|
"""Returns a specific Asset Administration Shell.
|
|
82
|
-
|
|
85
|
+
|
|
83
86
|
:param aas_id: ID of the AAS to retrieve
|
|
84
87
|
:return: Asset Administration Shells object or None if an error occurred
|
|
85
88
|
"""
|
|
86
89
|
content: dict = self._client.get_asset_administration_shell_by_id(aas_id)
|
|
87
|
-
|
|
90
|
+
|
|
88
91
|
if not content:
|
|
89
92
|
logger.warning(f"No shell found with ID '{aas_id}' on server.")
|
|
90
93
|
return None
|
|
91
|
-
|
|
94
|
+
|
|
92
95
|
return _to_object(content)
|
|
93
96
|
|
|
94
97
|
def get_asset_administration_shell_by_id_reference_aas_repository(self, aas_id: str) -> model.Reference | None:
|
|
@@ -97,12 +100,12 @@ class SdkWrapper():
|
|
|
97
100
|
:param aas_id: ID of the AAS reference to retrieve
|
|
98
101
|
:return: Asset Administration Shells reference object or None if an error occurred
|
|
99
102
|
"""
|
|
100
|
-
#workaround because serialization not working
|
|
103
|
+
# workaround because serialization not working
|
|
101
104
|
aas = self.get_asset_administration_shell_by_id(aas_id)
|
|
102
105
|
return model.ModelReference.from_referable(aas)
|
|
103
|
-
|
|
104
|
-
# content: dict = self._client.
|
|
105
|
-
# return
|
|
106
|
+
|
|
107
|
+
# content: dict = self._client.get_asset_administration_shell_by_id_reference_aas_repository(aas_id)
|
|
108
|
+
# return _to_object(content)
|
|
106
109
|
|
|
107
110
|
def get_submodel_by_id_aas_repository(self, aas_id: str, submodel_id: str) -> model.Submodel | None:
|
|
108
111
|
"""Returns the Submodel.
|
|
@@ -122,9 +125,9 @@ class SdkWrapper():
|
|
|
122
125
|
"""
|
|
123
126
|
return self._client.delete_asset_administration_shell_by_id(aas_id)
|
|
124
127
|
|
|
125
|
-
# endregion
|
|
128
|
+
# endregion
|
|
126
129
|
|
|
127
|
-
# region submodels
|
|
130
|
+
# region submodels
|
|
128
131
|
|
|
129
132
|
def post_submodel(self, submodel: model.Submodel) -> model.Submodel | None:
|
|
130
133
|
"""Creates a new Submodel.
|
|
@@ -186,15 +189,15 @@ class SdkWrapper():
|
|
|
186
189
|
if not content:
|
|
187
190
|
logger.warning(f"No submodel found with ID '{submodel_id}' on server.")
|
|
188
191
|
return None
|
|
189
|
-
|
|
192
|
+
|
|
190
193
|
return _to_object(content)
|
|
191
194
|
|
|
192
195
|
def patch_submodel_by_id(self, submodel_id: str, submodel: model.Submodel):
|
|
193
|
-
"""Updates an existing Submodel
|
|
196
|
+
"""Updates an existing Submodel.
|
|
194
197
|
|
|
195
198
|
:param submodel_id: Encoded ID of the Submodel to delete
|
|
196
199
|
:return: True if the patch was successful, False otherwise
|
|
197
|
-
"""
|
|
200
|
+
"""
|
|
198
201
|
sm_data = _to_dict(submodel)
|
|
199
202
|
return self._client.patch_submodel_by_id(submodel_id, sm_data)
|
|
200
203
|
|
|
@@ -206,15 +209,17 @@ class SdkWrapper():
|
|
|
206
209
|
"""
|
|
207
210
|
return self._client.delete_submodel_by_id(submodel_id)
|
|
208
211
|
|
|
209
|
-
def get_all_submodel_elements_submodel_repository(
|
|
210
|
-
|
|
211
|
-
|
|
212
|
+
def get_all_submodel_elements_submodel_repository(
|
|
213
|
+
self,
|
|
214
|
+
submodel_id: str,
|
|
215
|
+
) -> list[model.SubmodelElement] | None:
|
|
216
|
+
"""Returns all submodel elements including their hierarchy. !!!Serialization to model.SubmodelElement currently not possible.
|
|
212
217
|
|
|
213
218
|
:param submodel_id: Encoded ID of the Submodel to retrieve elements from
|
|
214
219
|
:return: List of Submodel elements or None if an error occurred
|
|
215
220
|
"""
|
|
216
221
|
content = self._client.get_all_submodel_elements_submodel_repository(submodel_id)
|
|
217
|
-
|
|
222
|
+
|
|
218
223
|
if not content:
|
|
219
224
|
return []
|
|
220
225
|
|
|
@@ -238,9 +243,8 @@ class SdkWrapper():
|
|
|
238
243
|
return submodel_elements
|
|
239
244
|
|
|
240
245
|
def post_submodel_element_submodel_repo(self, submodel_id: str, submodel_element: model.SubmodelElement) -> model.SubmodelElement | None:
|
|
241
|
-
"""Creates a new submodel element.
|
|
242
|
-
|
|
243
|
-
|
|
246
|
+
"""Creates a new submodel element. !!!Serialization to model.SubmodelElements currently not possible.
|
|
247
|
+
|
|
244
248
|
:param submodel_id: Encoded ID of the submodel to create elements for
|
|
245
249
|
:param submodel_element: Submodel element to create
|
|
246
250
|
:return: List of submodel element objects or None if an error occurred
|
|
@@ -249,18 +253,31 @@ class SdkWrapper():
|
|
|
249
253
|
content: dict = self._client.post_submodel_element_submodel_repo(submodel_id, sme_data)
|
|
250
254
|
return _to_object(content)
|
|
251
255
|
|
|
256
|
+
def get_submodel_element_by_path_submodel_repo(self, submodel_id: str, submodel_element_path: str) -> model.SubmodelElement | None:
|
|
257
|
+
"""Returns a specific submodel element from the Submodel at a specified path.
|
|
258
|
+
|
|
259
|
+
:param submodel_id: Encoded ID of the Submodel to retrieve element from
|
|
260
|
+
:param submodel_element_path: Path of the Submodel element to retrieve
|
|
261
|
+
:return: Submodel element object or None if an error occurred
|
|
262
|
+
"""
|
|
263
|
+
content: dict = self._client.get_submodel_element_by_path_submodel_repo(submodel_id, submodel_element_path)
|
|
264
|
+
return _to_object(content)
|
|
265
|
+
|
|
252
266
|
|
|
253
267
|
# endregion
|
|
254
268
|
|
|
269
|
+
|
|
255
270
|
def _to_object(content: dict) -> Any | None:
|
|
256
271
|
try:
|
|
257
272
|
dict_string = json.dumps(content)
|
|
273
|
+
print(dict_string)
|
|
258
274
|
return json.loads(dict_string, cls=basyx.aas.adapter.json.AASFromJsonDecoder)
|
|
259
275
|
except Exception as e:
|
|
260
276
|
logger.error(f"Decoding error: {e}")
|
|
261
277
|
logger.error(f"In JSON: {content}")
|
|
262
278
|
return None
|
|
263
|
-
|
|
279
|
+
|
|
280
|
+
|
|
264
281
|
def _to_dict(object: Any) -> dict | None:
|
|
265
282
|
try:
|
|
266
283
|
data_string = json.dumps(object, cls=basyx.aas.adapter.json.AASToJsonEncoder)
|
|
@@ -268,10 +285,12 @@ def _to_dict(object: Any) -> dict | None:
|
|
|
268
285
|
except Exception as e:
|
|
269
286
|
logger.error(f"Encoding error: {e}")
|
|
270
287
|
logger.error(f"In object: {object}")
|
|
271
|
-
return None
|
|
288
|
+
return None
|
|
289
|
+
|
|
272
290
|
|
|
273
291
|
# region wrapper
|
|
274
292
|
|
|
293
|
+
|
|
275
294
|
def create_wrapper_by_url(
|
|
276
295
|
base_url: str,
|
|
277
296
|
username: str = "",
|
|
@@ -304,17 +323,18 @@ def create_wrapper_by_url(
|
|
|
304
323
|
config_dict["connection_time_out"] = connection_time_out
|
|
305
324
|
config_dict["ssl_verify"] = ssl_verify
|
|
306
325
|
config_string = json.dumps(config_dict, indent=4)
|
|
307
|
-
|
|
326
|
+
|
|
308
327
|
wrapper = SdkWrapper()
|
|
309
|
-
client = _create_client(config_string, password)
|
|
310
|
-
|
|
328
|
+
client = _create_client(config_string, password)
|
|
329
|
+
|
|
311
330
|
if not client:
|
|
312
331
|
return None
|
|
313
|
-
|
|
332
|
+
|
|
314
333
|
wrapper._client = client
|
|
315
|
-
wrapper.base_url = client.base_url
|
|
334
|
+
wrapper.base_url = client.base_url
|
|
316
335
|
return wrapper
|
|
317
|
-
|
|
336
|
+
|
|
337
|
+
|
|
318
338
|
def create_wrapper_by_config(config_file: Path, password: str = "") -> SdkWrapper | None:
|
|
319
339
|
"""Create a wrapper for the BaSyx Python SDK from the given parameters.
|
|
320
340
|
|
|
@@ -332,12 +352,13 @@ def create_wrapper_by_config(config_file: Path, password: str = "") -> SdkWrappe
|
|
|
332
352
|
|
|
333
353
|
wrapper = SdkWrapper()
|
|
334
354
|
client = _create_client(config_string, password)
|
|
335
|
-
|
|
355
|
+
|
|
336
356
|
if not client:
|
|
337
357
|
return None
|
|
338
|
-
|
|
339
|
-
wrapper._client = client
|
|
340
|
-
wrapper.base_url = client.base_url
|
|
358
|
+
|
|
359
|
+
wrapper._client = client
|
|
360
|
+
wrapper.base_url = client.base_url
|
|
341
361
|
return wrapper
|
|
342
362
|
|
|
343
|
-
|
|
363
|
+
|
|
364
|
+
# endregion
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aas-http-client
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.8
|
|
4
4
|
Summary: Generic python HTTP client for communication with various types of AAS servers
|
|
5
5
|
Author-email: Daniel Klein <daniel.klein@em.ag>
|
|
6
6
|
License: # :em engineering methods AG Software License
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
aas_http_client/__init__.py,sha256=cAr1mQzWp0G0LKtkAOYzc9t95OY3jM3Aj4bKnxx0Dso,901
|
|
2
|
+
aas_http_client/client.py,sha256=1wsVZq9cOM01fA7qNcie_NNosoeCkE_fTKNV69Rc0vM,24267
|
|
3
|
+
aas_http_client/core/encoder.py,sha256=FS7P0FPakzFsGz70eRFDHQZFA_2nlKLlWIxavtnFrPg,660
|
|
4
|
+
aas_http_client/core/version_check.py,sha256=721Zs3xSRrJTYZtAxkaUWg9LLKtpU7oFM62DzQHZdE4,705
|
|
5
|
+
aas_http_client/demo/demo_process.py,sha256=6sN_N3QbA4iLUmzeg1Y_XOwVAuDNtwkR4grAg7EkjWM,3301
|
|
6
|
+
aas_http_client/demo/logging_handler.py,sha256=VJtZ4u3x_LhYZQtfNck7FuXhGFZm7gid0uDhvf9GjJ8,5596
|
|
7
|
+
aas_http_client/utilities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
+
aas_http_client/utilities/model_builder.py,sha256=EUqVvKgXiyJNtyUeFrL6ronfF4hiF1KCipxSaLj6EiE,4465
|
|
9
|
+
aas_http_client/wrapper/sdk_wrapper.py,sha256=siK73pRY8Hji_aGUxrRULli_2dH48Z6skgLqH8ujxPg,13539
|
|
10
|
+
aas_http_client-0.2.8.dist-info/licenses/LICENSE,sha256=ayt4HY-Tjoe1Uvj47j6UdNq8mEufKcKFangurChIHxQ,5990
|
|
11
|
+
aas_http_client-0.2.8.dist-info/METADATA,sha256=mfnLMhi9z8Z511NwnP7kWiX6Mt0dM7MnXxQ20pySLck,10333
|
|
12
|
+
aas_http_client-0.2.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
13
|
+
aas_http_client-0.2.8.dist-info/top_level.txt,sha256=vzvoz2vjeTLwpuz-Y-eEfoQ7T3byoaKshVlFMFH5NaM,16
|
|
14
|
+
aas_http_client-0.2.8.dist-info/RECORD,,
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
aas_http_client/__init__.py,sha256=cAr1mQzWp0G0LKtkAOYzc9t95OY3jM3Aj4bKnxx0Dso,901
|
|
2
|
-
aas_http_client/client.py,sha256=LEUh3cVZnOnqL37OQx3nrLaqqbMfROUnA47mv6Hrvz4,23118
|
|
3
|
-
aas_http_client/core/encoder.py,sha256=FS7P0FPakzFsGz70eRFDHQZFA_2nlKLlWIxavtnFrPg,660
|
|
4
|
-
aas_http_client/core/version_check.py,sha256=721Zs3xSRrJTYZtAxkaUWg9LLKtpU7oFM62DzQHZdE4,705
|
|
5
|
-
aas_http_client/demo/demo_process.py,sha256=Rutj6TAk9raCllSnfNYe2XODg_CrP_hBZMJPWEq93Yw,3374
|
|
6
|
-
aas_http_client/demo/logging_handler.py,sha256=VJtZ4u3x_LhYZQtfNck7FuXhGFZm7gid0uDhvf9GjJ8,5596
|
|
7
|
-
aas_http_client/utilities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
-
aas_http_client/utilities/model_builder.py,sha256=mL06SX208dMJHpiB-ol51JA9Bm3czoI8ELYTfismCq8,4633
|
|
9
|
-
aas_http_client/wrapper/sdk_wrapper.py,sha256=aRoMY2SAkp9f1Yjz1ZhvpnUJi3jyG58qkUWZZA32iu4,13017
|
|
10
|
-
aas_http_client-0.2.6.dist-info/licenses/LICENSE,sha256=ayt4HY-Tjoe1Uvj47j6UdNq8mEufKcKFangurChIHxQ,5990
|
|
11
|
-
aas_http_client-0.2.6.dist-info/METADATA,sha256=4RsyvDZ_JWTQq46ym1Bl7eN97wbMt0eidVObAWj3XKs,10333
|
|
12
|
-
aas_http_client-0.2.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
13
|
-
aas_http_client-0.2.6.dist-info/top_level.txt,sha256=vzvoz2vjeTLwpuz-Y-eEfoQ7T3byoaKshVlFMFH5NaM,16
|
|
14
|
-
aas_http_client-0.2.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|