aas-http-client 0.1.92__py3-none-any.whl → 0.2.1__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.
aas_http_client/client.py CHANGED
@@ -20,6 +20,7 @@ STATUS_CODE_200 = 200
20
20
  STATUS_CODE_201 = 201
21
21
  STATUS_CODE_202 = 202
22
22
  STATUS_CODE_204 = 204
23
+ STATUS_CODE_404 = 404
23
24
  HEADERS = {"Content-Type": "application/json"}
24
25
 
25
26
 
@@ -54,6 +55,9 @@ def log_response_errors(response: Response):
54
55
  result_error_messages.append(str(message))
55
56
  elif "error" in response_content_dict:
56
57
  result_error_messages.append(response_content_dict.get("error", ""))
58
+
59
+ if len(result_error_messages) == 0 and response.text:
60
+ result_error_messages.append(response.text)
57
61
 
58
62
  except json.JSONDecodeError:
59
63
  result_error_messages.append(response.content)
@@ -484,13 +488,14 @@ def create_client_by_config(config_file: Path, password: str = "") -> AasHttpCli
484
488
  :param password: password for the BaSyx server interface client, defaults to ""_
485
489
  :return: An instance of HttpClient initialized with the provided parameters.
486
490
  """
487
- logger.info(f"Create BaSyx server interface client from config file '{config_file}'")
491
+ config_file = config_file.resolve()
492
+ logger.info(f"Create AAS HTTP client from Configuration file '{config_file}'")
488
493
  if not config_file.exists():
489
494
  config_string = "{}"
490
- logger.warning(f"Server config file '{config_file}' not found. Using default config.")
495
+ logger.warning(f"Configuration file '{config_file}' not found. Using default configuration.")
491
496
  else:
492
497
  config_string = config_file.read_text(encoding="utf-8")
493
- logger.debug(f"Server config file '{config_file}' found.")
498
+ logger.debug(f"Configuration file '{config_file}' found.")
494
499
 
495
500
  return _create_client(config_string, password)
496
501
 
@@ -529,12 +534,12 @@ def _connect_to_api(client: AasHttpClient) -> bool:
529
534
  try:
530
535
  root = client.get_root()
531
536
  if root:
532
- logger.info(f"Connected to REST API at '{client.base_url}' successfully.")
537
+ logger.info(f"Connected to server API at '{client.base_url}' successfully.")
533
538
  return True
534
539
  except requests.exceptions.ConnectionError:
535
540
  pass
536
541
  if time.time() - start_time > client.connection_time_out:
537
- raise TimeoutError(f"Connection to REST API timed out after {client.connection_time_out} seconds.")
542
+ raise TimeoutError(f"Connection to server API timed out after {client.connection_time_out} seconds.")
538
543
 
539
544
  counter += 1
540
545
  logger.warning(f"Retrying connection (attempt: {counter})")
@@ -16,15 +16,23 @@ def start():
16
16
  aas_2 = _create_shell()
17
17
 
18
18
  client = _create_client()
19
- sdk_wrapper = _create_sdk_wrapper()
19
+ java_sdk_wrapper = _create_sdk_wrapper(Path("./aas_http_client/demo/java_server_config.json"))
20
+ dotnet_sdk_wrapper = _create_sdk_wrapper(Path("./aas_http_client/demo/dotnet_server_config.json"))
20
21
 
21
- exist_shells = sdk_wrapper.get_shells()
22
+ java_sdk_wrapper.get_shells_by_id(aas_1.id)
23
+ dotnet_sdk_wrapper.get_shells_by_id(aas_1.id)
24
+
25
+ java_sdk_wrapper.get_submodels_by_id(aas_1.id)
26
+ dotnet_sdk_wrapper.get_submodels_by_id(aas_1.id)
27
+
28
+ exist_shells = java_sdk_wrapper.get_shells()
29
+ exist_shells = dotnet_sdk_wrapper.get_shells()
22
30
 
23
31
  for shell in exist_shells:
24
32
  logger.warning(f"Delete shell '{shell.id}'")
25
- sdk_wrapper.delete_shells_by_id(shell.id)
33
+ java_sdk_wrapper.delete_shells_by_id(shell.id)
26
34
 
27
- sdk_wrapper.post_shells(aas_1)
35
+ java_sdk_wrapper.post_shells(aas_1)
28
36
 
29
37
 
30
38
  aas_dict_string = json.dumps(aas_2, cls=basyx.aas.adapter.json.AASToJsonEncoder)
@@ -53,7 +61,7 @@ def _create_client() -> AasHttpClient:
53
61
  """Create client for java servers."""
54
62
 
55
63
  try:
56
- file = Path("./demo/server_config.json")
64
+ file = Path("./aas_http_client/demo/java_server_config.json")
57
65
  client = create_client_by_config(file, password="")
58
66
  except Exception as e:
59
67
  logger.error(f"Failed to create client for {file}: {e}")
@@ -61,11 +69,11 @@ def _create_client() -> AasHttpClient:
61
69
 
62
70
  return client
63
71
 
64
- def _create_sdk_wrapper() -> SdkWrapper:
72
+ def _create_sdk_wrapper(config: Path) -> SdkWrapper:
65
73
  """Create client for java servers."""
66
74
 
67
75
  try:
68
- file = Path("./demo/server_config.json")
76
+ file = config
69
77
  client = create_wrapper_by_config(file, password="")
70
78
  except Exception as e:
71
79
  logger.error(f"Failed to create client for {file}: {e}")
@@ -3,10 +3,11 @@
3
3
  import json
4
4
  import logging
5
5
  from pathlib import Path
6
+ from typing import Any
6
7
 
7
8
  import basyx.aas.adapter.json
8
9
 
9
- from basyx.aas.model import AssetAdministrationShell, Reference, Submodel
10
+ from basyx.aas.model import AssetAdministrationShell, Reference, Submodel, ModelReference
10
11
  from aas_http_client.client import AasHttpClient, _create_client
11
12
  logger = logging.getLogger(__name__)
12
13
 
@@ -20,9 +21,7 @@ class SdkWrapper():
20
21
  :param aas: Asset Administration Shell to post
21
22
  :return: Response data as a dictionary or None if an error occurred
22
23
  """
23
- aas_data_string = json.dumps(aas, cls=basyx.aas.adapter.json.AASToJsonEncoder)
24
- aas_data = json.loads(aas_data_string)
25
-
24
+ aas_data = _to_dict(aas)
26
25
  return self._client.post_shells(aas_data)
27
26
 
28
27
  def put_shells(self, identifier: str, aas: AssetAdministrationShell) -> bool:
@@ -32,21 +31,17 @@ class SdkWrapper():
32
31
  :param aas: Asset Administration Shell data to update
33
32
  :return: True if the update was successful, False otherwise
34
33
  """
35
- aas_data_string = json.dumps(aas, cls=basyx.aas.adapter.json.AASToJsonEncoder)
36
- aas_data = json.loads(aas_data_string)
37
-
34
+ aas_data = _to_dict(aas)
38
35
  return self._client.put_shells(identifier, aas_data)
39
36
 
40
- def put_shells_submodels(self, aas_id: str, submodel_id: str, submodel: Submodel) -> bool:
37
+ def put_shells_submodels_by_id(self, aas_id: str, submodel_id: str, submodel: Submodel) -> bool:
41
38
  """Update a submodel by its ID for a specific Asset Administration Shell (AAS).
42
39
 
43
40
  :param aas_id: ID of the AAS to update the submodel for
44
41
  :param submodel: Submodel data to update
45
42
  :return: True if the update was successful, False otherwise
46
43
  """
47
- sm_data_string = json.dumps(submodel, cls=basyx.aas.adapter.json.AASToJsonEncoder)
48
- sm_data = json.loads(sm_data_string)
49
-
44
+ sm_data = _to_dict(submodel)
50
45
  return self._client.put_shells_submodels_by_id(aas_id, submodel_id, sm_data)
51
46
 
52
47
  def get_shells(self) -> list[AssetAdministrationShell] | None:
@@ -57,24 +52,24 @@ class SdkWrapper():
57
52
  content: dict = self._client.get_shells()
58
53
 
59
54
  if not content:
60
- logger.warning("No AAS found in the REST API.")
61
- return []
55
+ return None
62
56
 
63
57
  results: list = content.get("result", [])
64
58
  if not results:
65
- logger.warning("No AAS found in the REST API results.")
59
+ logger.warning("No shells found on server.")
66
60
  return []
67
61
 
68
62
  aas_list: list[AssetAdministrationShell] = []
69
63
 
70
64
  for result in results:
71
65
  if not isinstance(result, dict):
72
- logger.error(f"Invalid AAS data: {result}")
66
+ logger.error(f"Invalid shell data: {result}")
73
67
  return None
74
68
 
75
- aas_dict_string = json.dumps(result)
76
- aas = json.loads(aas_dict_string, cls=basyx.aas.adapter.json.AASFromJsonDecoder)
77
- aas_list.append(aas)
69
+ aas = _to_object(result)
70
+
71
+ if aas:
72
+ aas_list.append(aas)
78
73
 
79
74
  return aas_list
80
75
 
@@ -85,11 +80,20 @@ class SdkWrapper():
85
80
  :return: AAS object or None if an error occurred
86
81
  """
87
82
  content: dict = self._client.get_shells_by_id(aas_id)
88
- return json.load(content, cls=basyx.aas.adapter.json.AASFromJsonDecoder)
83
+
84
+ if not content:
85
+ logger.warning(f"No shell found with ID '{aas_id}' on server.")
86
+ return None
87
+
88
+ return _to_object(content)
89
89
 
90
90
  def get_shells_reference_by_id(self, aas_id: str) -> Reference | None:
91
- content: dict = self._client.get_shells_reference_by_id(aas_id)
92
- return json.load(content, cls=basyx.aas.adapter.json.AASFromJsonDecoder)
91
+ #workaround because serialization not working
92
+ aas = self.get_shells_by_id(aas_id)
93
+ return ModelReference.from_referable(aas)
94
+
95
+ # content: dict = self._client.get_shells_reference_by_id(aas_id)
96
+ # return json.loads(content, cls=basyx.aas.adapter.json.AASFromJsonDecoder)
93
97
 
94
98
  def get_shells_submodels_by_id(self, aas_id: str, submodel_id: str) -> Submodel | None:
95
99
  """Get a submodel by its ID for a specific Asset Administration Shell (AAS).
@@ -99,7 +103,7 @@ class SdkWrapper():
99
103
  :return: Submodel object or None if an error occurred
100
104
  """
101
105
  content: dict = self._client.get_shells_submodels_by_id(aas_id, submodel_id)
102
- return json.load(content, cls=basyx.aas.adapter.json.AASFromJsonDecoder)
106
+ return _to_object(content)
103
107
 
104
108
  def delete_shells_by_id(self, aas_id: str) -> bool:
105
109
  """Get an Asset Administration Shell (AAS) by its ID from the REST API.
@@ -115,9 +119,7 @@ class SdkWrapper():
115
119
  :param submodel: submodel data as a dictionary
116
120
  :return: Response data as a dictionary or None if an error occurred
117
121
  """
118
- sm_data_string = json.dumps(submodel, cls=basyx.aas.adapter.json.AASToJsonEncoder)
119
- sm_data = json.loads(sm_data_string)
120
-
122
+ sm_data = _to_dict(submodel)
121
123
  return self._client.post_submodels(sm_data)
122
124
 
123
125
  def put_submodels_by_id(self, identifier: str, submodel: Submodel) -> bool:
@@ -127,9 +129,7 @@ class SdkWrapper():
127
129
  :param submodel: Submodel data to update
128
130
  :return: True if the update was successful, False otherwise
129
131
  """
130
- sm_data_string = json.dumps(submodel, cls=basyx.aas.adapter.json.AASToJsonEncoder)
131
- sm_data = json.loads(sm_data_string)
132
-
132
+ sm_data = _to_dict(submodel)
133
133
  return self._client.put_submodels_by_id(identifier, sm_data)
134
134
 
135
135
  def get_submodels(self) -> list[Submodel] | None:
@@ -140,12 +140,11 @@ class SdkWrapper():
140
140
  content: list = self._client.get_submodels()
141
141
 
142
142
  if not content:
143
- logger.warning("No submodels found in the REST API.")
144
143
  return []
145
144
 
146
145
  results: list = content.get("result", [])
147
146
  if not results:
148
- logger.warning("No submodels found in the REST API results.")
147
+ logger.warning("No submodels found on server.")
149
148
  return []
150
149
 
151
150
  submodels: list[Submodel] = []
@@ -155,9 +154,10 @@ class SdkWrapper():
155
154
  logger.error(f"Invalid submodel data: {result}")
156
155
  return None
157
156
 
158
- sm_dict_string = json.dumps(result)
159
- submodel = json.loads(sm_dict_string, cls=basyx.aas.adapter.json.AASFromJsonDecoder)
160
- submodels.append(submodel)
157
+ submodel = _to_object(result)
158
+
159
+ if submodel:
160
+ submodels.append(submodel)
161
161
 
162
162
  return submodels
163
163
 
@@ -170,20 +170,14 @@ class SdkWrapper():
170
170
  content = self._client.get_submodels_by_id(submodel_id)
171
171
 
172
172
  if not content:
173
- logger.warning(f"No submodel found with ID '{submodel_id}' in the REST API.")
173
+ logger.warning(f"No submodel found with ID '{submodel_id}' on server.")
174
174
  return None
175
175
 
176
- if not isinstance(content, dict):
177
- logger.error(f"Invalid submodel data: {content}")
178
- return None
179
- #
180
- return json.loads(content, cls=basyx.aas.adapter.json.AASFromJsonDecoder)
176
+ return _to_object(content)
181
177
 
182
178
  def patch_submodel_by_id(self, submodel_id: str, submodel: Submodel):
183
- sm_dict_string = json.dumps(submodel, cls=basyx.aas.adapter.json.AASToJsonEncoder)
184
- sm_dict = json.loads(sm_dict_string)
185
-
186
- return self._client.patch_submodel_by_id(submodel_id, sm_dict)
179
+ sm_data = _to_dict(submodel)
180
+ return self._client.patch_submodel_by_id(submodel_id, sm_data)
187
181
 
188
182
  def delete_submodels_by_id(self, submodel_id: str) -> bool:
189
183
  """Delete a submodel by its ID from the REST API.
@@ -193,6 +187,24 @@ class SdkWrapper():
193
187
  """
194
188
  return self._client.delete_submodels_by_id(submodel_id)
195
189
 
190
+ def _to_object(content: dict) -> Any | None:
191
+ try:
192
+ dict_string = json.dumps(content)
193
+ return json.loads(dict_string, cls=basyx.aas.adapter.json.AASFromJsonDecoder)
194
+ except Exception as e:
195
+ logger.error(f"Decoding error: {e}")
196
+ logger.error(f"In JSON: {content}")
197
+ return None
198
+
199
+ def _to_dict(object: Any) -> dict | None:
200
+ try:
201
+ data_string = json.dumps(object, cls=basyx.aas.adapter.json.AASToJsonEncoder)
202
+ return json.loads(data_string)
203
+ except Exception as e:
204
+ logger.error(f"Encoding error: {e}")
205
+ logger.error(f"In object: {object}")
206
+ return None
207
+
196
208
  def create_wrapper_by_url(
197
209
  base_url: str,
198
210
  username: str = "",
@@ -227,7 +239,12 @@ def create_wrapper_by_url(
227
239
  config_string = json.dumps(config_dict, indent=4)
228
240
 
229
241
  wrapper = SdkWrapper()
230
- wrapper._client = _create_client(config_string, password)
242
+ client = _create_client(config_string, password)
243
+
244
+ if not client:
245
+ return None
246
+
247
+ wrapper._client = client
231
248
  return wrapper
232
249
 
233
250
 
@@ -239,14 +256,19 @@ def create_wrapper_by_config(config_file: Path, password: str = "") -> AasHttpCl
239
256
  :param password: password for the BaSyx server interface client, defaults to ""_
240
257
  :return: An instance of HttpClient initialized with the provided parameters.
241
258
  """
242
- logger.info(f"Create BaSyx server interface client from config file '{config_file}'")
259
+ logger.info(f"Create BaSyx Python SDK wrapper from configuration file '{config_file}'")
243
260
  if not config_file.exists():
244
261
  config_string = "{}"
245
- logger.warning(f"Server config file '{config_file}' not found. Using default config.")
262
+ logger.warning(f"Configuration file '{config_file}' not found. Using default config.")
246
263
  else:
247
264
  config_string = config_file.read_text(encoding="utf-8")
248
- logger.debug(f"Server config file '{config_file}' found.")
265
+ logger.debug(f"Configuration file '{config_file}' found.")
249
266
 
250
267
  wrapper = SdkWrapper()
251
- wrapper._client = _create_client(config_string, password)
268
+ client = _create_client(config_string, password)
269
+
270
+ if not client:
271
+ return None
272
+
273
+ wrapper._client = client
252
274
  return wrapper
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aas-http-client
3
- Version: 0.1.92
3
+ Version: 0.2.1
4
4
  Summary: Generic HTTP client for communicating 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
@@ -155,6 +155,8 @@ For a detailed introduction, please read [Getting Started](docs/getting_started.
155
155
  pip install aas-http-client
156
156
  ````
157
157
 
158
+ ### Client
159
+
158
160
  ```python
159
161
  from aas_http_client import create_client_by_url
160
162
 
@@ -164,3 +166,15 @@ client = create_client_by_url(
164
166
 
165
167
  print(client.get_shells())
166
168
  ```
169
+
170
+ ### SDK Wrapper
171
+
172
+ ```python
173
+ from aas_http_client.wrapper.sdk_wrapper import create_wrapper_by_config
174
+
175
+ wrapper = create_wrapper_by_config(
176
+ base_url="http://myaasserver:5043/"
177
+ )
178
+
179
+ print(wrapper.get_shells())
180
+ ```
@@ -0,0 +1,14 @@
1
+ aas_http_client/__init__.py,sha256=cAr1mQzWp0G0LKtkAOYzc9t95OY3jM3Aj4bKnxx0Dso,901
2
+ aas_http_client/client.py,sha256=6d3g9VNhex1JrZwIXtBTopSTw3bsf5NZBSWG5mHYuQg,20705
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=ESR0ETJdEWXHZRswcuNh9qArStFyHFWCNYxhJjLB0tA,2616
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=bL4hy3uHh1Y_uL6KmLIfo9ORiUqWNlyToJrAt8G1rpw,3877
9
+ aas_http_client/wrapper/sdk_wrapper.py,sha256=MClsjWDuKDMN_R5b9vEkbxn_sFQ-UhGN3DBzWkLiVQU,10314
10
+ aas_http_client-0.2.1.dist-info/licenses/LICENSE,sha256=ayt4HY-Tjoe1Uvj47j6UdNq8mEufKcKFangurChIHxQ,5990
11
+ aas_http_client-0.2.1.dist-info/METADATA,sha256=JRrDg3PIaAk5rfSuZkXkEln3QBOwMCBXjKKakwOgIRM,9137
12
+ aas_http_client-0.2.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
13
+ aas_http_client-0.2.1.dist-info/top_level.txt,sha256=vzvoz2vjeTLwpuz-Y-eEfoQ7T3byoaKshVlFMFH5NaM,16
14
+ aas_http_client-0.2.1.dist-info/RECORD,,
@@ -1,14 +0,0 @@
1
- aas_http_client/__init__.py,sha256=cAr1mQzWp0G0LKtkAOYzc9t95OY3jM3Aj4bKnxx0Dso,901
2
- aas_http_client/client.py,sha256=d4s90n48oJkeIiAQWR8OxJVeZGXz-heQMPGMREy3hQg,20512
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=-9-oQEi_B08W-POl2SVP4COodGPHN3mTw9rrPgLLpeY,2170
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=bL4hy3uHh1Y_uL6KmLIfo9ORiUqWNlyToJrAt8G1rpw,3877
9
- aas_http_client/wrapper/sdk_wrapper.py,sha256=O61Q32zlWxsNqpb4p811GbPd2Un9VGLY_pXR5Q-0QTg,10395
10
- aas_http_client-0.1.92.dist-info/licenses/LICENSE,sha256=ayt4HY-Tjoe1Uvj47j6UdNq8mEufKcKFangurChIHxQ,5990
11
- aas_http_client-0.1.92.dist-info/METADATA,sha256=yKi6mzy9KtnAjoq7sjj4d-ROoAftfb7sVtRKs8ueG9A,8913
12
- aas_http_client-0.1.92.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
13
- aas_http_client-0.1.92.dist-info/top_level.txt,sha256=vzvoz2vjeTLwpuz-Y-eEfoQ7T3byoaKshVlFMFH5NaM,16
14
- aas_http_client-0.1.92.dist-info/RECORD,,