aas-http-client 0.4.2__py3-none-any.whl → 0.4.4__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/classes/auth_classes.py +21 -0
- aas_http_client/client.py +200 -30
- aas_http_client/demo/demo_process.py +23 -10
- aas_http_client/wrapper/sdk_wrapper.py +30 -18
- {aas_http_client-0.4.2.dist-info → aas_http_client-0.4.4.dist-info}/METADATA +1 -1
- {aas_http_client-0.4.2.dist-info → aas_http_client-0.4.4.dist-info}/RECORD +9 -8
- {aas_http_client-0.4.2.dist-info → aas_http_client-0.4.4.dist-info}/WHEEL +0 -0
- {aas_http_client-0.4.2.dist-info → aas_http_client-0.4.4.dist-info}/licenses/LICENSE +0 -0
- {aas_http_client-0.4.2.dist-info → aas_http_client-0.4.4.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from pydantic import BaseModel, PrivateAttr, ValidationError
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class BasicAuthConfig(BaseModel):
|
|
5
|
+
username: str
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ServiceProviderAuthConfig(BaseModel):
|
|
9
|
+
token_url: str
|
|
10
|
+
client_id: str
|
|
11
|
+
grant_type: str = "client_credentials"
|
|
12
|
+
header_name: str = "Authorization"
|
|
13
|
+
_client_secret: str = PrivateAttr(default=None)
|
|
14
|
+
|
|
15
|
+
def set_client_secret(self, client_secret: str) -> None:
|
|
16
|
+
self._client_secret = client_secret
|
|
17
|
+
|
|
18
|
+
def get_client_secret(self) -> str:
|
|
19
|
+
if self._client_secret is None:
|
|
20
|
+
raise ValueError("Client secret has not been set.")
|
|
21
|
+
return self._client_secret
|
aas_http_client/client.py
CHANGED
|
@@ -4,10 +4,8 @@ import json
|
|
|
4
4
|
import logging
|
|
5
5
|
import time
|
|
6
6
|
from pathlib import Path
|
|
7
|
-
from typing import Any
|
|
8
7
|
|
|
9
8
|
import basyx.aas.adapter.json
|
|
10
|
-
import basyx.aas.adapter.json.json_serialization as js
|
|
11
9
|
import requests
|
|
12
10
|
from basyx.aas.model import Reference, Submodel
|
|
13
11
|
from pydantic import BaseModel, PrivateAttr, ValidationError
|
|
@@ -15,6 +13,7 @@ from requests import Session
|
|
|
15
13
|
from requests.auth import HTTPBasicAuth
|
|
16
14
|
from requests.models import Response
|
|
17
15
|
|
|
16
|
+
from aas_http_client.classes.auth_classes import BasicAuthConfig, ServiceProviderAuthConfig
|
|
18
17
|
from aas_http_client.core.encoder import decode_base_64
|
|
19
18
|
|
|
20
19
|
logger = logging.getLogger(__name__)
|
|
@@ -74,16 +73,22 @@ class AasHttpClient(BaseModel):
|
|
|
74
73
|
"""Represents a AasHttpClient to communicate with a REST API."""
|
|
75
74
|
|
|
76
75
|
base_url: str = "http://javaaasserver:5060/"
|
|
77
|
-
|
|
76
|
+
basic_auth: BasicAuthConfig | None = None
|
|
77
|
+
service_provider_auth: ServiceProviderAuthConfig | None = None
|
|
78
78
|
https_proxy: str | None = None
|
|
79
79
|
http_proxy: str | None = None
|
|
80
80
|
time_out: int = 200
|
|
81
81
|
connection_time_out: int = 100
|
|
82
82
|
ssl_verify: bool = True
|
|
83
83
|
trust_env: bool = True
|
|
84
|
+
auth_service_provider: str | None = None
|
|
84
85
|
_session: Session = PrivateAttr(default=None)
|
|
85
86
|
|
|
86
|
-
def initialize(
|
|
87
|
+
def initialize(
|
|
88
|
+
self,
|
|
89
|
+
basic_auth_password: str,
|
|
90
|
+
service_provider_auth_client_secret: str,
|
|
91
|
+
):
|
|
87
92
|
"""Initialize the AasHttpClient with the given URL, username and password.
|
|
88
93
|
|
|
89
94
|
:param password: password
|
|
@@ -92,10 +97,17 @@ class AasHttpClient(BaseModel):
|
|
|
92
97
|
self.base_url = self.base_url[:-1]
|
|
93
98
|
|
|
94
99
|
self._session = requests.Session()
|
|
95
|
-
|
|
100
|
+
|
|
101
|
+
self._session.auth = HTTPBasicAuth("", "")
|
|
102
|
+
if self.basic_auth:
|
|
103
|
+
self._session.auth = HTTPBasicAuth(self.basic_auth.username, basic_auth_password)
|
|
104
|
+
|
|
96
105
|
self._session.verify = self.ssl_verify
|
|
97
106
|
self._session.trust_env = self.trust_env
|
|
98
107
|
|
|
108
|
+
if self.service_provider_auth:
|
|
109
|
+
self.service_provider_auth.set_client_secret(service_provider_auth_client_secret)
|
|
110
|
+
|
|
99
111
|
if self.https_proxy:
|
|
100
112
|
self._session.proxies.update({"https": self.https_proxy})
|
|
101
113
|
if self.http_proxy:
|
|
@@ -108,6 +120,9 @@ class AasHttpClient(BaseModel):
|
|
|
108
120
|
"""
|
|
109
121
|
url = f"{self.base_url}/shells"
|
|
110
122
|
|
|
123
|
+
if self.service_provider_auth:
|
|
124
|
+
self._set_token_by_client_credentials()
|
|
125
|
+
|
|
111
126
|
try:
|
|
112
127
|
response = self._session.get(url, headers=HEADERS, timeout=10)
|
|
113
128
|
logger.debug(f"Call REST API url '{response.url}'")
|
|
@@ -123,6 +138,29 @@ class AasHttpClient(BaseModel):
|
|
|
123
138
|
content = response.content.decode("utf-8")
|
|
124
139
|
return json.loads(content)
|
|
125
140
|
|
|
141
|
+
def _set_token_by_client_credentials(self) -> dict | None:
|
|
142
|
+
if self.service_provider_auth is None:
|
|
143
|
+
logger.error("Service provider authentication is not configured.")
|
|
144
|
+
return None
|
|
145
|
+
|
|
146
|
+
if self.service_provider_auth.grant_type == "password":
|
|
147
|
+
token = get_token_by_password(
|
|
148
|
+
self.service_provider_auth.token_url,
|
|
149
|
+
self.service_provider_auth.client_id,
|
|
150
|
+
self.service_provider_auth.get_client_secret(),
|
|
151
|
+
self.time_out,
|
|
152
|
+
)
|
|
153
|
+
else:
|
|
154
|
+
token = get_token_by_basic_auth(
|
|
155
|
+
self.service_provider_auth.token_url,
|
|
156
|
+
self.service_provider_auth.client_id,
|
|
157
|
+
self.service_provider_auth.get_client_secret(),
|
|
158
|
+
self.time_out,
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
if token:
|
|
162
|
+
self._session.headers.update({self.service_provider_auth.auth_header_name: f"Bearer {token}"})
|
|
163
|
+
|
|
126
164
|
# region shells
|
|
127
165
|
|
|
128
166
|
def post_asset_administration_shell(self, aas_data: dict) -> dict | None:
|
|
@@ -134,6 +172,9 @@ class AasHttpClient(BaseModel):
|
|
|
134
172
|
url = f"{self.base_url}/shells"
|
|
135
173
|
logger.debug(f"Call REST API url '{url}'")
|
|
136
174
|
|
|
175
|
+
if self.service_provider_auth:
|
|
176
|
+
self._set_token_by_client_credentials()
|
|
177
|
+
|
|
137
178
|
try:
|
|
138
179
|
response = self._session.post(url, headers=HEADERS, json=aas_data, timeout=self.time_out)
|
|
139
180
|
logger.debug(f"Call REST API url '{response.url}'")
|
|
@@ -159,6 +200,9 @@ class AasHttpClient(BaseModel):
|
|
|
159
200
|
decoded_identifier: str = decode_base_64(identifier)
|
|
160
201
|
url = f"{self.base_url}/shells/{decoded_identifier}"
|
|
161
202
|
|
|
203
|
+
if self.service_provider_auth:
|
|
204
|
+
self._set_token_by_client_credentials()
|
|
205
|
+
|
|
162
206
|
try:
|
|
163
207
|
response = self._session.put(url, headers=HEADERS, json=aas_data, timeout=self.time_out)
|
|
164
208
|
logger.debug(f"Call REST API url '{response.url}'")
|
|
@@ -184,6 +228,9 @@ class AasHttpClient(BaseModel):
|
|
|
184
228
|
decoded_submodel_id: str = decode_base_64(submodel_id)
|
|
185
229
|
url = f"{self.base_url}/shells/{decoded_aas_id}/submodels/{decoded_submodel_id}"
|
|
186
230
|
|
|
231
|
+
if self.service_provider_auth:
|
|
232
|
+
self._set_token_by_client_credentials()
|
|
233
|
+
|
|
187
234
|
try:
|
|
188
235
|
response = self._session.put(url, headers=HEADERS, json=submodel_data, timeout=self.time_out)
|
|
189
236
|
logger.debug(f"Call REST API url '{response.url}'")
|
|
@@ -205,6 +252,9 @@ class AasHttpClient(BaseModel):
|
|
|
205
252
|
"""
|
|
206
253
|
url = f"{self.base_url}/shells"
|
|
207
254
|
|
|
255
|
+
if self.service_provider_auth:
|
|
256
|
+
self._set_token_by_client_credentials()
|
|
257
|
+
|
|
208
258
|
try:
|
|
209
259
|
response = self._session.get(url, headers=HEADERS, timeout=self.time_out)
|
|
210
260
|
logger.debug(f"Call REST API url '{response.url}'")
|
|
@@ -229,6 +279,9 @@ class AasHttpClient(BaseModel):
|
|
|
229
279
|
decoded_aas_id: str = decode_base_64(aas_id)
|
|
230
280
|
url = f"{self.base_url}/shells/{decoded_aas_id}"
|
|
231
281
|
|
|
282
|
+
if self.service_provider_auth:
|
|
283
|
+
self._set_token_by_client_credentials()
|
|
284
|
+
|
|
232
285
|
try:
|
|
233
286
|
response = self._session.get(url, headers=HEADERS, timeout=self.time_out)
|
|
234
287
|
logger.debug(f"Call REST API url '{response.url}'")
|
|
@@ -253,6 +306,9 @@ class AasHttpClient(BaseModel):
|
|
|
253
306
|
decoded_aas_id: str = decode_base_64(aas_id)
|
|
254
307
|
url = f"{self.base_url}/shells/{decoded_aas_id}/$reference"
|
|
255
308
|
|
|
309
|
+
if self.service_provider_auth:
|
|
310
|
+
self._set_token_by_client_credentials()
|
|
311
|
+
|
|
256
312
|
try:
|
|
257
313
|
response = self._session.get(url, headers=HEADERS, timeout=self.time_out)
|
|
258
314
|
logger.debug(f"Call REST API url '{response.url}'")
|
|
@@ -279,7 +335,9 @@ class AasHttpClient(BaseModel):
|
|
|
279
335
|
decoded_submodel_id: str = decode_base_64(submodel_id)
|
|
280
336
|
|
|
281
337
|
url = f"{self.base_url}/shells/{decoded_aas_id}/submodels/{decoded_submodel_id}"
|
|
282
|
-
|
|
338
|
+
|
|
339
|
+
if self.service_provider_auth:
|
|
340
|
+
self._set_token_by_client_credentials()
|
|
283
341
|
|
|
284
342
|
try:
|
|
285
343
|
response = self._session.get(url, headers=HEADERS, timeout=self.time_out)
|
|
@@ -305,6 +363,9 @@ class AasHttpClient(BaseModel):
|
|
|
305
363
|
decoded_aas_id: str = decode_base_64(aas_id)
|
|
306
364
|
url = f"{self.base_url}/shells/{decoded_aas_id}"
|
|
307
365
|
|
|
366
|
+
if self.service_provider_auth:
|
|
367
|
+
self._set_token_by_client_credentials()
|
|
368
|
+
|
|
308
369
|
try:
|
|
309
370
|
response = self._session.delete(url, headers=HEADERS, timeout=self.time_out)
|
|
310
371
|
logger.debug(f"Call REST API url '{response.url}'")
|
|
@@ -331,6 +392,9 @@ class AasHttpClient(BaseModel):
|
|
|
331
392
|
"""
|
|
332
393
|
url = f"{self.base_url}/submodels"
|
|
333
394
|
|
|
395
|
+
if self.service_provider_auth:
|
|
396
|
+
self._set_token_by_client_credentials()
|
|
397
|
+
|
|
334
398
|
try:
|
|
335
399
|
response = self._session.post(url, headers=HEADERS, json=submodel_data, timeout=self.time_out)
|
|
336
400
|
logger.debug(f"Call REST API url '{response.url}'")
|
|
@@ -356,6 +420,9 @@ class AasHttpClient(BaseModel):
|
|
|
356
420
|
decoded_identifier: str = decode_base_64(identifier)
|
|
357
421
|
url = f"{self.base_url}/submodels/{decoded_identifier}"
|
|
358
422
|
|
|
423
|
+
if self.service_provider_auth:
|
|
424
|
+
self._set_token_by_client_credentials()
|
|
425
|
+
|
|
359
426
|
try:
|
|
360
427
|
response = self._session.put(url, headers=HEADERS, json=submodel_data, timeout=self.time_out)
|
|
361
428
|
logger.debug(f"Call REST API url '{response.url}'")
|
|
@@ -377,6 +444,9 @@ class AasHttpClient(BaseModel):
|
|
|
377
444
|
"""
|
|
378
445
|
url = f"{self.base_url}/submodels"
|
|
379
446
|
|
|
447
|
+
if self.service_provider_auth:
|
|
448
|
+
self._set_token_by_client_credentials()
|
|
449
|
+
|
|
380
450
|
try:
|
|
381
451
|
response = self._session.get(url, headers=HEADERS, timeout=self.time_out)
|
|
382
452
|
logger.debug(f"Call REST API url '{response.url}'")
|
|
@@ -401,6 +471,9 @@ class AasHttpClient(BaseModel):
|
|
|
401
471
|
decoded_submodel_id: str = decode_base_64(submodel_id)
|
|
402
472
|
url = f"{self.base_url}/submodels/{decoded_submodel_id}"
|
|
403
473
|
|
|
474
|
+
if self.service_provider_auth:
|
|
475
|
+
self._set_token_by_client_credentials()
|
|
476
|
+
|
|
404
477
|
try:
|
|
405
478
|
response = self._session.get(url, headers=HEADERS, timeout=self.time_out)
|
|
406
479
|
logger.debug(f"Call REST API url '{response.url}'")
|
|
@@ -425,6 +498,9 @@ class AasHttpClient(BaseModel):
|
|
|
425
498
|
decoded_submodel_id: str = decode_base_64(submodel_id)
|
|
426
499
|
url = f"{self.base_url}/submodels/{decoded_submodel_id}"
|
|
427
500
|
|
|
501
|
+
if self.service_provider_auth:
|
|
502
|
+
self._set_token_by_client_credentials()
|
|
503
|
+
|
|
428
504
|
try:
|
|
429
505
|
response = self._session.patch(url, headers=HEADERS, json=submodel_data, timeout=self.time_out)
|
|
430
506
|
logger.debug(f"Call REST API url '{response.url}'")
|
|
@@ -448,6 +524,9 @@ class AasHttpClient(BaseModel):
|
|
|
448
524
|
decoded_submodel_id: str = decode_base_64(submodel_id)
|
|
449
525
|
url = f"{self.base_url}/submodels/{decoded_submodel_id}"
|
|
450
526
|
|
|
527
|
+
if self.service_provider_auth:
|
|
528
|
+
self._set_token_by_client_credentials()
|
|
529
|
+
|
|
451
530
|
try:
|
|
452
531
|
response = self._session.delete(url, headers=HEADERS, timeout=self.time_out)
|
|
453
532
|
logger.debug(f"Call REST API url '{response.url}'")
|
|
@@ -471,6 +550,9 @@ class AasHttpClient(BaseModel):
|
|
|
471
550
|
decoded_submodel_id: str = decode_base_64(submodel_id)
|
|
472
551
|
url = f"{self.base_url}/submodels/{decoded_submodel_id}/submodel-elements"
|
|
473
552
|
|
|
553
|
+
if self.service_provider_auth:
|
|
554
|
+
self._set_token_by_client_credentials()
|
|
555
|
+
|
|
474
556
|
try:
|
|
475
557
|
response = self._session.get(url, headers=HEADERS, timeout=self.time_out)
|
|
476
558
|
logger.debug(f"Call REST API url '{response.url}'")
|
|
@@ -495,6 +577,9 @@ class AasHttpClient(BaseModel):
|
|
|
495
577
|
decoded_submodel_id: str = decode_base_64(submodel_id)
|
|
496
578
|
url = f"{self.base_url}/submodels/{decoded_submodel_id}/submodel-elements"
|
|
497
579
|
|
|
580
|
+
if self.service_provider_auth:
|
|
581
|
+
self._set_token_by_client_credentials()
|
|
582
|
+
|
|
498
583
|
try:
|
|
499
584
|
response = self._session.post(url, headers=HEADERS, json=submodel_element_data, timeout=self.time_out)
|
|
500
585
|
logger.debug(f"Call REST API url '{response.url}'")
|
|
@@ -521,6 +606,9 @@ class AasHttpClient(BaseModel):
|
|
|
521
606
|
decoded_submodel_id: str = decode_base_64(submodel_id)
|
|
522
607
|
url = f"{self.base_url}/submodels/{decoded_submodel_id}/submodel-elements/{submodel_element_path}"
|
|
523
608
|
|
|
609
|
+
if self.service_provider_auth:
|
|
610
|
+
self._set_token_by_client_credentials()
|
|
611
|
+
|
|
524
612
|
try:
|
|
525
613
|
response = self._session.post(url, headers=HEADERS, json=submodel_element_data, timeout=self.time_out)
|
|
526
614
|
logger.debug(f"Call REST API url '{response.url}'")
|
|
@@ -547,6 +635,9 @@ class AasHttpClient(BaseModel):
|
|
|
547
635
|
|
|
548
636
|
url = f"{self.base_url}/submodels/{decoded_submodel_id}/submodel-elements/{submodel_element_path}"
|
|
549
637
|
|
|
638
|
+
if self.service_provider_auth:
|
|
639
|
+
self._set_token_by_client_credentials()
|
|
640
|
+
|
|
550
641
|
try:
|
|
551
642
|
response = self._session.get(url, headers=HEADERS, timeout=self.time_out)
|
|
552
643
|
logger.debug(f"Call REST API url '{response.url}'")
|
|
@@ -573,6 +664,9 @@ class AasHttpClient(BaseModel):
|
|
|
573
664
|
|
|
574
665
|
url = f"{self.base_url}/submodels/{decoded_submodel_id}/submodel-elements/{submodel_element_path}"
|
|
575
666
|
|
|
667
|
+
if self.service_provider_auth:
|
|
668
|
+
self._set_token_by_client_credentials()
|
|
669
|
+
|
|
576
670
|
try:
|
|
577
671
|
response = self._session.delete(url, headers=HEADERS, timeout=self.time_out)
|
|
578
672
|
logger.debug(f"Call REST API url '{response.url}'")
|
|
@@ -599,6 +693,9 @@ class AasHttpClient(BaseModel):
|
|
|
599
693
|
|
|
600
694
|
url = f"{self.base_url}/submodels/{decoded_submodel_id}/submodel-elements/{submodel_element_path}/$value"
|
|
601
695
|
|
|
696
|
+
if self.service_provider_auth:
|
|
697
|
+
self._set_token_by_client_credentials()
|
|
698
|
+
|
|
602
699
|
try:
|
|
603
700
|
response = self._session.patch(url, headers=HEADERS, json=value, timeout=self.time_out)
|
|
604
701
|
logger.debug(f"Call REST API url '{response.url}'")
|
|
@@ -619,10 +716,68 @@ class AasHttpClient(BaseModel):
|
|
|
619
716
|
# region client
|
|
620
717
|
|
|
621
718
|
|
|
719
|
+
def get_token_by_basic_auth(endpoint: str, username: str, password: str, timeout=200) -> dict | None:
|
|
720
|
+
"""Get token from a specific authentication service provider by basic authentication.
|
|
721
|
+
|
|
722
|
+
:param endpoint: Get token endpoint for the authentication service provider
|
|
723
|
+
:param username: Username for the authentication service provider
|
|
724
|
+
:param password: Password for the authentication service provider
|
|
725
|
+
:param timeout: Timeout for the API calls, defaults to 200
|
|
726
|
+
:return: Access token or None if an error occurred
|
|
727
|
+
"""
|
|
728
|
+
data = {"grant_type": "client_credentials"}
|
|
729
|
+
|
|
730
|
+
auth = HTTPBasicAuth(username, password)
|
|
731
|
+
|
|
732
|
+
try:
|
|
733
|
+
response = requests.post(endpoint, auth=auth, data=data, timeout=timeout)
|
|
734
|
+
logger.info(f"Request URL: {response.url}")
|
|
735
|
+
response.raise_for_status()
|
|
736
|
+
return response.json().get("access_token")
|
|
737
|
+
except requests.RequestException as e:
|
|
738
|
+
logger.error(f"Error getting token: {e}")
|
|
739
|
+
return None
|
|
740
|
+
|
|
741
|
+
|
|
742
|
+
def get_token_by_password(endpoint: str, username: str, password: str, timeout=200) -> dict | None:
|
|
743
|
+
"""Get token from a specific authentication service provider by username and password.
|
|
744
|
+
|
|
745
|
+
:param endpoint: Get token endpoint for the authentication service provider
|
|
746
|
+
:param username: Username for the authentication service provider
|
|
747
|
+
:param password: Password for the authentication service provider
|
|
748
|
+
:param timeout: Timeout for the API calls, defaults to 200
|
|
749
|
+
:return: Access token or None if an error occurred
|
|
750
|
+
"""
|
|
751
|
+
data = {"grant_type": "password", "username": username, "password": password}
|
|
752
|
+
|
|
753
|
+
return _get_token(endpoint, data, timeout)
|
|
754
|
+
|
|
755
|
+
|
|
756
|
+
def _get_token(endpoint: str, data: dict[str, str], timeout: int = 200) -> dict | None:
|
|
757
|
+
"""Get token from a specific authentication service provider.
|
|
758
|
+
|
|
759
|
+
:param endpoint: Get token endpoint for the authentication service provider
|
|
760
|
+
:param data: Data for the authentication service provider
|
|
761
|
+
:param timeout: Timeout for the API calls, defaults to 200
|
|
762
|
+
:return: Access token or None if an error occurred
|
|
763
|
+
"""
|
|
764
|
+
try:
|
|
765
|
+
response = requests.post(endpoint, json=data, timeout=timeout)
|
|
766
|
+
logger.info(f"Request URL: {response.url}")
|
|
767
|
+
response.raise_for_status()
|
|
768
|
+
return response.json().get("access_token")
|
|
769
|
+
except requests.RequestException as e:
|
|
770
|
+
logger.error(f"Error getting token: {e}")
|
|
771
|
+
return None
|
|
772
|
+
|
|
773
|
+
|
|
622
774
|
def create_client_by_url(
|
|
623
775
|
base_url: str,
|
|
624
|
-
|
|
625
|
-
|
|
776
|
+
basic_auth_username: str = "",
|
|
777
|
+
basic_auth_password: str = "",
|
|
778
|
+
service_provider_auth_client_id: str = "",
|
|
779
|
+
service_provider_auth_client_secret: str = "",
|
|
780
|
+
service_provider_auth_token_url: str = "",
|
|
626
781
|
http_proxy: str = "",
|
|
627
782
|
https_proxy: str = "",
|
|
628
783
|
time_out: int = 200,
|
|
@@ -633,10 +788,10 @@ def create_client_by_url(
|
|
|
633
788
|
"""Create a HTTP client for a AAS server connection from the given parameters.
|
|
634
789
|
|
|
635
790
|
:param base_url: Base URL of the AAS server, e.g. "http://basyx_python_server:80/"_
|
|
636
|
-
:param username: Username for the AAS server, defaults to ""
|
|
637
|
-
:param
|
|
638
|
-
:param http_proxy: http proxy URL, defaults to ""
|
|
639
|
-
:param https_proxy: https proxy URL, defaults to ""
|
|
791
|
+
:param username: Username for the AAS server, defaults to ""
|
|
792
|
+
:param basic_auth_password: password for the BaSyx server basic auth, defaults to ""
|
|
793
|
+
:param http_proxy: http proxy URL, defaults to ""
|
|
794
|
+
:param https_proxy: https proxy URL, defaults to ""
|
|
640
795
|
:param time_out: Timeout for the API calls, defaults to 200
|
|
641
796
|
:param connection_time_out: Timeout for the connection to the API, defaults to 60
|
|
642
797
|
:param ssl_verify: Whether to verify SSL certificates, defaults to True
|
|
@@ -646,34 +801,45 @@ def create_client_by_url(
|
|
|
646
801
|
logger.info(f"Create AAS server http client from URL '{base_url}'.")
|
|
647
802
|
config_dict: dict[str, str] = {}
|
|
648
803
|
config_dict["base_url"] = base_url
|
|
649
|
-
config_dict["username"] = username
|
|
650
804
|
config_dict["http_proxy"] = http_proxy
|
|
651
805
|
config_dict["https_proxy"] = https_proxy
|
|
652
806
|
config_dict["time_out"] = time_out
|
|
653
807
|
config_dict["connection_time_out"] = connection_time_out
|
|
654
808
|
config_dict["ssl_verify"] = ssl_verify
|
|
655
809
|
config_dict["trust_env"] = trust_env
|
|
656
|
-
|
|
810
|
+
config_dict["basic_auth"] = None
|
|
811
|
+
config_dict["service_provider_auth"] = None
|
|
812
|
+
|
|
813
|
+
if basic_auth_password and basic_auth_username:
|
|
814
|
+
config_dict["basic_auth"] = {"username": basic_auth_username}
|
|
815
|
+
|
|
816
|
+
if service_provider_auth_client_id and service_provider_auth_client_secret and service_provider_auth_token_url:
|
|
817
|
+
config_dict["service_provider_auth"] = {
|
|
818
|
+
"client_id": service_provider_auth_client_id,
|
|
819
|
+
"token_url": service_provider_auth_token_url,
|
|
820
|
+
}
|
|
657
821
|
|
|
822
|
+
return create_client_by_dict(config_dict, basic_auth_password, service_provider_auth_client_secret)
|
|
658
823
|
|
|
659
|
-
|
|
824
|
+
|
|
825
|
+
def create_client_by_dict(configuration: dict, basic_auth_password: str = "", service_provider_auth_client_secret: str = "") -> AasHttpClient | None:
|
|
660
826
|
"""Create a HTTP client for a AAS server connection from the given configuration.
|
|
661
827
|
|
|
662
828
|
:param configuration: Dictionary containing the BaSyx server connection settings.
|
|
663
|
-
:param
|
|
829
|
+
:param basic_auth_password: Password for the AAS server basic auth, defaults to ""
|
|
664
830
|
:return: An instance of Http client initialized with the provided parameters.
|
|
665
831
|
"""
|
|
666
832
|
logger.info("Create AAS server http client from dictionary.")
|
|
667
833
|
config_string = json.dumps(configuration, indent=4)
|
|
668
834
|
|
|
669
|
-
return _create_client(config_string,
|
|
835
|
+
return _create_client(config_string, basic_auth_password, service_provider_auth_client_secret)
|
|
670
836
|
|
|
671
837
|
|
|
672
|
-
def create_client_by_config(config_file: Path,
|
|
838
|
+
def create_client_by_config(config_file: Path, basic_auth_password: str = "", service_provider_auth_client_secret: str = "") -> AasHttpClient | None:
|
|
673
839
|
"""Create a HTTP client for a AAS server connection from a given configuration file.
|
|
674
840
|
|
|
675
841
|
:param config_file: Path to the configuration file containing the AAS server connection settings.
|
|
676
|
-
:param
|
|
842
|
+
:param basic_auth_password: password for the BaSyx server basic auth, defaults to ""
|
|
677
843
|
:return: An instance of Http client initialized with the provided parameters.
|
|
678
844
|
"""
|
|
679
845
|
config_file = config_file.resolve()
|
|
@@ -685,24 +851,28 @@ def create_client_by_config(config_file: Path, password: str = "") -> AasHttpCli
|
|
|
685
851
|
config_string = config_file.read_text(encoding="utf-8")
|
|
686
852
|
logger.debug(f"Configuration file '{config_file}' found.")
|
|
687
853
|
|
|
688
|
-
return _create_client(config_string,
|
|
854
|
+
return _create_client(config_string, basic_auth_password, service_provider_auth_client_secret)
|
|
689
855
|
|
|
690
856
|
|
|
691
|
-
def _create_client(config_string: str,
|
|
857
|
+
def _create_client(config_string: str, basic_auth_password: str, service_provider_auth_client_secret: str) -> AasHttpClient | None:
|
|
692
858
|
try:
|
|
693
859
|
client = AasHttpClient.model_validate_json(config_string)
|
|
694
860
|
except ValidationError as ve:
|
|
695
861
|
raise ValidationError(f"Invalid BaSyx server configuration file: {ve}") from ve
|
|
696
862
|
|
|
697
|
-
logger.info(
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
f"
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
863
|
+
logger.info("Using server configuration:")
|
|
864
|
+
logger.info(f"base_url: '{client.base_url}'")
|
|
865
|
+
logger.info(f"timeout: '{client.time_out}'")
|
|
866
|
+
|
|
867
|
+
if client.basic_auth:
|
|
868
|
+
logger.info(f"basic_auth: '{client.basic_auth.username}'")
|
|
869
|
+
if client.service_provider_auth:
|
|
870
|
+
logger.info(f"service_provider_auth: '{client.service_provider_auth.token_url}': {client.service_provider_auth.client_id}'")
|
|
871
|
+
|
|
872
|
+
logger.info(f"https_proxy: '{client.https_proxy}'")
|
|
873
|
+
logger.info(f"http_proxy: '{client.http_proxy}'")
|
|
874
|
+
logger.info(f"connection_timeout: '{client.connection_time_out}'.")
|
|
875
|
+
client.initialize(basic_auth_password, service_provider_auth_client_secret)
|
|
706
876
|
|
|
707
877
|
# test the connection to the REST API
|
|
708
878
|
connected = _connect_to_api(client)
|
|
@@ -5,9 +5,9 @@ from pathlib import Path
|
|
|
5
5
|
|
|
6
6
|
from basyx.aas import model
|
|
7
7
|
|
|
8
|
-
from aas_http_client
|
|
8
|
+
from aas_http_client import client as aas_client
|
|
9
9
|
from aas_http_client.utilities import model_builder, sdk_tools
|
|
10
|
-
from aas_http_client.wrapper
|
|
10
|
+
from aas_http_client.wrapper import sdk_wrapper
|
|
11
11
|
|
|
12
12
|
logger = logging.getLogger(__name__)
|
|
13
13
|
|
|
@@ -21,20 +21,33 @@ def start() -> None:
|
|
|
21
21
|
|
|
22
22
|
# create a submodel
|
|
23
23
|
sm_short_id: str = model_builder.create_unique_short_id("poc_sm")
|
|
24
|
-
submodel = model_builder.create_base_submodel(sm_short_id)
|
|
24
|
+
submodel = model_builder.create_base_submodel(sm_short_id, sm_short_id)
|
|
25
25
|
# add submodel element to submodel
|
|
26
26
|
# submodel.submodel_element.add(sme)
|
|
27
27
|
|
|
28
28
|
# create an AAS
|
|
29
29
|
aas_short_id: str = model_builder.create_unique_short_id("poc_aas")
|
|
30
|
-
aas = model_builder.create_base_ass(aas_short_id)
|
|
30
|
+
aas = model_builder.create_base_ass(aas_short_id, aas_short_id)
|
|
31
31
|
|
|
32
32
|
# add submodel to AAS
|
|
33
33
|
sdk_tools.add_submodel_to_aas(aas, submodel)
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
client = aas_client.create_client_by_url(
|
|
36
|
+
"http://javaaasserver:8075/",
|
|
37
|
+
service_provider_auth_client_id="fluid40",
|
|
38
|
+
service_provider_auth_client_secret="LdFB4jRrMMkgcVWgFkOVdDVDXtQ5os8w",
|
|
39
|
+
service_provider_auth_token_url="https://aurora-fluid40.iqstruct-engineering.de/auth/realms/BaSyx/protocol/openid-connect/token",
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
client = aas_client.create_client_by_config(Path("./aas_http_client/demo/java_server_config.yml"))
|
|
37
43
|
|
|
44
|
+
# tmp = get_token_by_basic_auth(
|
|
45
|
+
# "https://aurora-fluid40.iqstruct-engineering.de/auth/realms/BaSyx/protocol/openid-connect/token",
|
|
46
|
+
# "fluid40",
|
|
47
|
+
# "LdFB4jRrMMkgcVWgFkOVdDVDXtQ5os8w",
|
|
48
|
+
# )
|
|
49
|
+
|
|
50
|
+
wrapper = _create_sdk_wrapper(Path("./aas_http_client/demo/python_server_config.yml"))
|
|
38
51
|
for existing_shell in wrapper.get_all_asset_administration_shells():
|
|
39
52
|
logger.warning(f"Delete shell '{existing_shell.id}'")
|
|
40
53
|
wrapper.delete_asset_administration_shell_by_id(existing_shell.id)
|
|
@@ -64,7 +77,7 @@ def start() -> None:
|
|
|
64
77
|
wrapper.delete_submodel_by_id(existing_submodel.id)
|
|
65
78
|
|
|
66
79
|
|
|
67
|
-
def _create_client(config: Path) -> AasHttpClient:
|
|
80
|
+
def _create_client(config: Path) -> aas_client.AasHttpClient:
|
|
68
81
|
"""Create a HTTP client from a given configuration file.
|
|
69
82
|
|
|
70
83
|
:param config: Given configuration file
|
|
@@ -72,7 +85,7 @@ def _create_client(config: Path) -> AasHttpClient:
|
|
|
72
85
|
"""
|
|
73
86
|
try:
|
|
74
87
|
file = config
|
|
75
|
-
client = create_client_by_config(file, password="")
|
|
88
|
+
client = aas_client.create_client_by_config(file, password="")
|
|
76
89
|
|
|
77
90
|
except Exception as e:
|
|
78
91
|
logger.error(f"Failed to create client for {file}: {e}")
|
|
@@ -80,7 +93,7 @@ def _create_client(config: Path) -> AasHttpClient:
|
|
|
80
93
|
return client
|
|
81
94
|
|
|
82
95
|
|
|
83
|
-
def _create_sdk_wrapper(config: Path) -> SdkWrapper:
|
|
96
|
+
def _create_sdk_wrapper(config: Path) -> sdk_wrapper.SdkWrapper:
|
|
84
97
|
"""Create a SDK wrapper from a given configuration file.
|
|
85
98
|
|
|
86
99
|
:param config: Given configuration file
|
|
@@ -88,7 +101,7 @@ def _create_sdk_wrapper(config: Path) -> SdkWrapper:
|
|
|
88
101
|
"""
|
|
89
102
|
try:
|
|
90
103
|
file = config
|
|
91
|
-
client = create_wrapper_by_config(file,
|
|
104
|
+
client = sdk_wrapper.create_wrapper_by_config(file, basic_auth_password="")
|
|
92
105
|
|
|
93
106
|
except Exception as e:
|
|
94
107
|
logger.error(f"Failed to create client for {file}: {e}")
|
|
@@ -19,13 +19,13 @@ class SdkWrapper:
|
|
|
19
19
|
_client: AasHttpClient = None
|
|
20
20
|
base_url: str = ""
|
|
21
21
|
|
|
22
|
-
def __init__(self, config_string: str,
|
|
22
|
+
def __init__(self, config_string: str, basic_auth_password: str = "", service_provider_auth_client_secret: str = ""):
|
|
23
23
|
"""Initializes the wrapper with the given configuration.
|
|
24
24
|
|
|
25
25
|
:param config_string: Configuration string for the BaSyx server connection.
|
|
26
|
-
:param
|
|
26
|
+
:param basic_auth_password: Password for the BaSyx server interface client, defaults to "".
|
|
27
27
|
"""
|
|
28
|
-
client = _create_client(config_string,
|
|
28
|
+
client = _create_client(config_string, basic_auth_password, service_provider_auth_client_secret)
|
|
29
29
|
|
|
30
30
|
if not client:
|
|
31
31
|
raise ValueError("Failed to create AAS HTTP client with the provided configuration.")
|
|
@@ -317,8 +317,11 @@ class SdkWrapper:
|
|
|
317
317
|
|
|
318
318
|
def create_wrapper_by_url(
|
|
319
319
|
base_url: str,
|
|
320
|
-
|
|
321
|
-
|
|
320
|
+
basic_auth_username: str = "",
|
|
321
|
+
basic_auth_password: str = "",
|
|
322
|
+
service_provider_auth_client_id: str = "",
|
|
323
|
+
service_provider_auth_client_secret: str = "",
|
|
324
|
+
service_provider_auth_token_url: str = "",
|
|
322
325
|
http_proxy: str = "",
|
|
323
326
|
https_proxy: str = "",
|
|
324
327
|
time_out: int = 200,
|
|
@@ -328,11 +331,11 @@ def create_wrapper_by_url(
|
|
|
328
331
|
) -> SdkWrapper | None:
|
|
329
332
|
"""Create a wrapper for a AAS server connection from the given parameters.
|
|
330
333
|
|
|
331
|
-
:param base_url: base URL of the BaSyx server, e.g. "http://basyx_python_server:80/"
|
|
332
|
-
:param
|
|
333
|
-
:param
|
|
334
|
-
:param http_proxy: http proxy URL, defaults to ""
|
|
335
|
-
:param https_proxy: https proxy URL, defaults to ""
|
|
334
|
+
:param base_url: base URL of the BaSyx server, e.g. "http://basyx_python_server:80/"
|
|
335
|
+
:param basic_auth_username: username for the BaSyx server interface client, defaults to ""
|
|
336
|
+
:param basic_auth_password: password for the BaSyx server basic auth, defaults to ""
|
|
337
|
+
:param http_proxy: http proxy URL, defaults to ""
|
|
338
|
+
:param https_proxy: https proxy URL, defaults to ""
|
|
336
339
|
:param time_out: timeout for the API calls, defaults to 200
|
|
337
340
|
:param connection_time_out: timeout for the connection to the API, defaults to 60
|
|
338
341
|
:param ssl_verify: whether to verify SSL certificates, defaults to True
|
|
@@ -342,33 +345,42 @@ def create_wrapper_by_url(
|
|
|
342
345
|
logger.info(f"Create AAS server wrapper from URL '{base_url}'.")
|
|
343
346
|
config_dict: dict[str, str] = {}
|
|
344
347
|
config_dict["base_url"] = base_url
|
|
345
|
-
config_dict["username"] = username
|
|
346
348
|
config_dict["http_proxy"] = http_proxy
|
|
347
349
|
config_dict["https_proxy"] = https_proxy
|
|
348
350
|
config_dict["time_out"] = time_out
|
|
349
351
|
config_dict["connection_time_out"] = connection_time_out
|
|
350
352
|
config_dict["ssl_verify"] = ssl_verify
|
|
351
353
|
config_dict["trust_env"] = trust_env
|
|
352
|
-
return create_wrapper_by_dict(config_dict, password)
|
|
353
354
|
|
|
355
|
+
if basic_auth_password and basic_auth_username:
|
|
356
|
+
config_dict["basic_auth"] = {"username": basic_auth_username}
|
|
354
357
|
|
|
355
|
-
|
|
358
|
+
if service_provider_auth_client_id and service_provider_auth_client_secret and service_provider_auth_token_url:
|
|
359
|
+
config_dict["service_provider_auth"] = {
|
|
360
|
+
"client_id": service_provider_auth_client_id,
|
|
361
|
+
"token_url": service_provider_auth_token_url,
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
return create_wrapper_by_dict(config_dict, basic_auth_password)
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
def create_wrapper_by_dict(configuration: dict, basic_auth_password: str = "", service_provider_auth_client_secret: str = "") -> SdkWrapper | None:
|
|
356
368
|
"""Create a wrapper for a AAS server connection from the given configuration.
|
|
357
369
|
|
|
358
370
|
:param config: Dictionary containing the BaSyx server connection settings.
|
|
359
|
-
:param
|
|
371
|
+
:param basic_auth_password: password for the BaSyx server basic auth, defaults to ""
|
|
360
372
|
:return: An instance of SdkWrapper initialized with the provided parameters.
|
|
361
373
|
"""
|
|
362
374
|
logger.info("Create AAS server wrapper from dictionary.")
|
|
363
375
|
config_string = json.dumps(configuration, indent=4)
|
|
364
|
-
return SdkWrapper(config_string,
|
|
376
|
+
return SdkWrapper(config_string, basic_auth_password, service_provider_auth_client_secret)
|
|
365
377
|
|
|
366
378
|
|
|
367
|
-
def create_wrapper_by_config(config_file: Path,
|
|
379
|
+
def create_wrapper_by_config(config_file: Path, basic_auth_password: str = "", service_provider_auth_client_secret: str = "") -> SdkWrapper | None:
|
|
368
380
|
"""Create a wrapper for a AAS server connection from a given configuration file.
|
|
369
381
|
|
|
370
382
|
:param config_file: Path to the configuration file containing the BaSyx server connection settings.
|
|
371
|
-
:param
|
|
383
|
+
:param basic_auth_password: password for the BaSyx server basic auth, defaults to ""
|
|
372
384
|
:return: An instance of SdkWrapper initialized with the provided parameters.
|
|
373
385
|
"""
|
|
374
386
|
logger.info(f"Create AAS wrapper client from configuration file '{config_file}'.")
|
|
@@ -378,7 +390,7 @@ def create_wrapper_by_config(config_file: Path, password: str = "") -> SdkWrappe
|
|
|
378
390
|
else:
|
|
379
391
|
config_string = config_file.read_text(encoding="utf-8")
|
|
380
392
|
logger.debug(f"Configuration file '{config_file}' found.")
|
|
381
|
-
return SdkWrapper(config_string,
|
|
393
|
+
return SdkWrapper(config_string, basic_auth_password, service_provider_auth_client_secret)
|
|
382
394
|
|
|
383
395
|
|
|
384
396
|
# endregion
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aas-http-client
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.4
|
|
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
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
aas_http_client/__init__.py,sha256=bBfrdXUHvukisXIj0CcnNUHUw8_7nrdnfQRve8nM_3U,982
|
|
2
|
-
aas_http_client/client.py,sha256=
|
|
2
|
+
aas_http_client/client.py,sha256=wU6IhAR5F52EF7XCZokQ79cGpGEFBDl22_nalsxg5mQ,35458
|
|
3
|
+
aas_http_client/classes/auth_classes.py,sha256=us1oDlBpI7R3xp2pcr9ZJ_AAaM65J-g8neq-d1M2FHw,619
|
|
3
4
|
aas_http_client/core/encoder.py,sha256=FS7P0FPakzFsGz70eRFDHQZFA_2nlKLlWIxavtnFrPg,660
|
|
4
5
|
aas_http_client/core/version_check.py,sha256=9dR0Q6jCFygH_ctj4vyrjerpHvolT87ayengZFlBWCw,708
|
|
5
|
-
aas_http_client/demo/demo_process.py,sha256=
|
|
6
|
+
aas_http_client/demo/demo_process.py,sha256=uCyvotKWRItlhjNX7ek7ek3r5gXZ3jSARvvzcKhzyqw,3971
|
|
6
7
|
aas_http_client/demo/logging_handler.py,sha256=VJtZ4u3x_LhYZQtfNck7FuXhGFZm7gid0uDhvf9GjJ8,5596
|
|
7
8
|
aas_http_client/utilities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
9
|
aas_http_client/utilities/model_builder.py,sha256=SxAv8DJkKksykw_2gtTV2jHu-MRzevOVzspn807_7VA,4680
|
|
9
10
|
aas_http_client/utilities/sdk_tools.py,sha256=CDD0mus8jOi-irgPO6dQHulmEyu8BSG_05Mol_nirK0,2008
|
|
10
|
-
aas_http_client/wrapper/sdk_wrapper.py,sha256=
|
|
11
|
-
aas_http_client-0.4.
|
|
12
|
-
aas_http_client-0.4.
|
|
13
|
-
aas_http_client-0.4.
|
|
14
|
-
aas_http_client-0.4.
|
|
15
|
-
aas_http_client-0.4.
|
|
11
|
+
aas_http_client/wrapper/sdk_wrapper.py,sha256=OneN_9rtFSYUjnQWFcQneg8cih5YhkyLER4NZTAgUR0,16443
|
|
12
|
+
aas_http_client-0.4.4.dist-info/licenses/LICENSE,sha256=ayt4HY-Tjoe1Uvj47j6UdNq8mEufKcKFangurChIHxQ,5990
|
|
13
|
+
aas_http_client-0.4.4.dist-info/METADATA,sha256=Hc-PAH5vOcsBfFbI_DmubGpPfM6g1C6G85pFqeby9uM,10467
|
|
14
|
+
aas_http_client-0.4.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
15
|
+
aas_http_client-0.4.4.dist-info/top_level.txt,sha256=vzvoz2vjeTLwpuz-Y-eEfoQ7T3byoaKshVlFMFH5NaM,16
|
|
16
|
+
aas_http_client-0.4.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|