OpenSMI-Core 0.2.1__tar.gz → 0.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. opensmi_core-0.3/PKG-INFO +84 -0
  2. {opensmi_core-0.2.1 → opensmi_core-0.3}/pyproject.toml +3 -1
  3. opensmi_core-0.3/src/OpenSMI_Core.egg-info/PKG-INFO +84 -0
  4. opensmi_core-0.3/src/OpenSMI_Core.egg-info/scm_version.json +8 -0
  5. {opensmi_core-0.2.1 → opensmi_core-0.3}/src/opensmi/core/subscription_manager.py +72 -29
  6. opensmi_core-0.2.1/PKG-INFO +0 -32
  7. opensmi_core-0.2.1/src/OpenSMI_Core.egg-info/PKG-INFO +0 -32
  8. opensmi_core-0.2.1/src/OpenSMI_Core.egg-info/scm_version.json +0 -8
  9. {opensmi_core-0.2.1 → opensmi_core-0.3}/.github/workflows/api-docs.yml +0 -0
  10. {opensmi_core-0.2.1 → opensmi_core-0.3}/.github/workflows/python-publish.yml +0 -0
  11. {opensmi_core-0.2.1 → opensmi_core-0.3}/.gitignore +0 -0
  12. {opensmi_core-0.2.1 → opensmi_core-0.3}/.gitlab-ci.yml +0 -0
  13. {opensmi_core-0.2.1 → opensmi_core-0.3}/LICENSE +0 -0
  14. {opensmi_core-0.2.1 → opensmi_core-0.3}/LICENSES/MIT.txt +0 -0
  15. {opensmi_core-0.2.1 → opensmi_core-0.3}/README.md +0 -0
  16. {opensmi_core-0.2.1 → opensmi_core-0.3}/setup.cfg +0 -0
  17. {opensmi_core-0.2.1 → opensmi_core-0.3}/src/OpenSMI_Core.egg-info/SOURCES.txt +0 -0
  18. {opensmi_core-0.2.1 → opensmi_core-0.3}/src/OpenSMI_Core.egg-info/dependency_links.txt +0 -0
  19. {opensmi_core-0.2.1 → opensmi_core-0.3}/src/OpenSMI_Core.egg-info/requires.txt +0 -0
  20. {opensmi_core-0.2.1 → opensmi_core-0.3}/src/OpenSMI_Core.egg-info/scm_file_list.json +0 -0
  21. {opensmi_core-0.2.1 → opensmi_core-0.3}/src/OpenSMI_Core.egg-info/top_level.txt +0 -0
  22. {opensmi_core-0.2.1 → opensmi_core-0.3}/src/opensmi/core/__init__.py +0 -0
  23. {opensmi_core-0.2.1 → opensmi_core-0.3}/src/opensmi/core/async_task_mixin.py +0 -0
  24. {opensmi_core-0.2.1 → opensmi_core-0.3}/src/opensmi/core/base_server.py +0 -0
  25. {opensmi_core-0.2.1 → opensmi_core-0.3}/src/opensmi/core/base_ua_object.py +0 -0
  26. {opensmi_core-0.2.1 → opensmi_core-0.3}/src/opensmi/core/config.py +0 -0
  27. {opensmi_core-0.2.1 → opensmi_core-0.3}/src/opensmi/core/enums.py +0 -0
  28. {opensmi_core-0.2.1 → opensmi_core-0.3}/src/opensmi/core/errors.py +0 -0
  29. {opensmi_core-0.2.1 → opensmi_core-0.3}/src/opensmi/core/frozen.py +0 -0
  30. {opensmi_core-0.2.1 → opensmi_core-0.3}/src/opensmi/core/hook.py +0 -0
  31. {opensmi_core-0.2.1 → opensmi_core-0.3}/src/opensmi/core/lifecycle_mixin.py +0 -0
  32. {opensmi_core-0.2.1 → opensmi_core-0.3}/src/opensmi/core/logging.py +0 -0
  33. {opensmi_core-0.2.1 → opensmi_core-0.3}/src/opensmi/core/meta.py +0 -0
  34. {opensmi_core-0.2.1 → opensmi_core-0.3}/src/opensmi/core/mixin_helpers.py +0 -0
  35. {opensmi_core-0.2.1 → opensmi_core-0.3}/src/opensmi/core/protocols.py +0 -0
  36. {opensmi_core-0.2.1 → opensmi_core-0.3}/src/opensmi/core/repr_mixin.py +0 -0
  37. {opensmi_core-0.2.1 → opensmi_core-0.3}/src/opensmi/core/signal.py +0 -0
  38. {opensmi_core-0.2.1 → opensmi_core-0.3}/src/opensmi/core/ua.py +0 -0
  39. {opensmi_core-0.2.1 → opensmi_core-0.3}/src/opensmi/core/ua_enums.py +0 -0
  40. {opensmi_core-0.2.1 → opensmi_core-0.3}/src/opensmi/core/ua_node_util.py +0 -0
  41. {opensmi_core-0.2.1 → opensmi_core-0.3}/src/opensmi/core/unit_all.py +0 -0
  42. {opensmi_core-0.2.1 → opensmi_core-0.3}/src/opensmi/core/unit_base.py +0 -0
  43. {opensmi_core-0.2.1 → opensmi_core-0.3}/src/opensmi/core/unset.py +0 -0
  44. {opensmi_core-0.2.1 → opensmi_core-0.3}/tests/test_signal.py +0 -0
  45. {opensmi_core-0.2.1 → opensmi_core-0.3}/tests/test_unit.py +0 -0
  46. {opensmi_core-0.2.1 → opensmi_core-0.3}/tools/auto_generate_units.py +0 -0
@@ -0,0 +1,84 @@
1
+ Metadata-Version: 2.4
2
+ Name: OpenSMI-Core
3
+ Version: 0.3
4
+ Summary: Smart Machine Interface core functionality for server and client applications.
5
+ Author-email: Carsten Harms <Carsten.Harms@dfki.de>, Simon Jungbluth <Simon.Jungbluth@smartfactory.de>
6
+ License-Expression: MIT
7
+ Classifier: Development Status :: 4 - Beta
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: Intended Audience :: Information Technology
10
+ Classifier: Intended Audience :: Manufacturing
11
+ Classifier: Intended Audience :: Science/Research
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
17
+ Classifier: Topic :: Communications
18
+ Classifier: Topic :: Scientific/Engineering
19
+ Classifier: Topic :: Scientific/Engineering :: Interface Engine/Protocol Translator
20
+ Classifier: Topic :: Software Development :: Embedded Systems
21
+ Classifier: Topic :: Software Development :: Libraries
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.11
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSES/MIT.txt
26
+ Requires-Dist: asyncua<3,>=2.0.1
27
+ Requires-Dist: structlog>=26
28
+ Requires-Dist: typing-extensions>=4.16.0
29
+ Provides-Extra: rich
30
+ Requires-Dist: rich>=15.0.0; extra == "rich"
31
+ Requires-Dist: colorama>=0.4; sys_platform == "win32" and extra == "rich"
32
+ Provides-Extra: json
33
+ Requires-Dist: orjson<4,>=3; extra == "json"
34
+ Dynamic: license-file
35
+
36
+ ![OpenSMI Logo](https://smartfactory.de/wp-content/uploads/2026/09/Logo_OpenSMI.png)
37
+
38
+ [![Docs](https://img.shields.io/badge/docs-online-blue)](https://smartfactory-kl.github.io/opensmi-core/)
39
+ [![PyPI version](https://img.shields.io/pypi/v/opensmi-core.svg)](https://pypi.org/project/opensmi-core/)
40
+ [![Python versions](https://img.shields.io/pypi/pyversions/opensmi-core.svg)](https://pypi.org/project/opensmi-core/)
41
+ [![License](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
42
+
43
+ # OpenSMI Core
44
+
45
+ Core functionality for other OpenSMI packages such as:
46
+
47
+ - [OpenSMI Client](https://github.com/SmartFactory-KL/opensmi-client)
48
+ - [OpenSMI Server](https://github.com/SmartFactory-KL/opensmi-server)
49
+
50
+ ## Features
51
+
52
+ - (Nested) Configuration parsing into dataclasses from TOML files (See [config.py](src/opensmi/core/config.py))
53
+ - Lifecycle management via mixin and `@lifecycle` decorators, allowing explicit ordering
54
+ (See [lifecycle_mixin.py](src/opensmi/core/lifecycle_mixin.py))
55
+ - Simple callbacks via `Signal` (similar to [aiosignal](https://pypi.org/project/aiosignal/), but without freezing)
56
+ (See [signal.py](src/opensmi/core/signal.py))
57
+ - [asyncua](https://pypi.org/project/asyncua/) (OPC UA) helpers
58
+ - Node helper functions (See [ua_node_util.py](src/opensmi/core/ua_node_util.py))
59
+ - SubscriptionManager (See [subscription_manager.py](src/opensmi/core/subscription_manager.py))
60
+ - Enums for OpenSMI machine, component and skill states
61
+ - All [UN/CEFACT-Rec20](https://unece.org/trade/documents/2021/06/uncefact-rec20-0) units as a type-checkable enum.
62
+ (See [unit_all.py](src/opensmi/core/unit_all.py))
63
+ - [Structured Logging](https://pypi.org/project/structlog/) configuration (See [logging.py](src/opensmi/core/logging.py))
64
+
65
+ > [!warning]
66
+ > This library is currently pre-1.0 — expect refactoring outside above-mentioned functionality.
67
+
68
+ ## Installation
69
+
70
+ Requires Python 3.11+.
71
+
72
+ ```bash
73
+ pip install opensmi-core
74
+ ```
75
+
76
+ ## Project Status
77
+
78
+ OpenSMI began as a closed-source project at [SmartFactory-KL](https://smartfactory.de/), in active use in our model
79
+ factory since 2020. Its OPC UA information model has been refined across many iterations of research and
80
+ demonstrator use. The framework was open-sourced in 2026 following substantial refactoring and cleanup.
81
+
82
+ ## License
83
+
84
+ [MIT License](LICENSE)
@@ -5,12 +5,14 @@ build-backend = "setuptools.build_meta"
5
5
  [project]
6
6
  name = "OpenSMI-Core"
7
7
  dynamic = ["version"]
8
-
8
+ readme = "README.md"
9
9
  description = "Smart Machine Interface core functionality for server and client applications."
10
10
  authors = [
11
11
  { name = "Carsten Harms", email = "Carsten.Harms@dfki.de" },
12
12
  { name = "Simon Jungbluth", email = "Simon.Jungbluth@smartfactory.de" },
13
13
  ]
14
+ license = "MIT"
15
+ license-files = ["LICENSES/MIT.txt"]
14
16
 
15
17
  # see https://pypi.org/classifiers/
16
18
  classifiers = [
@@ -0,0 +1,84 @@
1
+ Metadata-Version: 2.4
2
+ Name: OpenSMI-Core
3
+ Version: 0.3
4
+ Summary: Smart Machine Interface core functionality for server and client applications.
5
+ Author-email: Carsten Harms <Carsten.Harms@dfki.de>, Simon Jungbluth <Simon.Jungbluth@smartfactory.de>
6
+ License-Expression: MIT
7
+ Classifier: Development Status :: 4 - Beta
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: Intended Audience :: Information Technology
10
+ Classifier: Intended Audience :: Manufacturing
11
+ Classifier: Intended Audience :: Science/Research
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
17
+ Classifier: Topic :: Communications
18
+ Classifier: Topic :: Scientific/Engineering
19
+ Classifier: Topic :: Scientific/Engineering :: Interface Engine/Protocol Translator
20
+ Classifier: Topic :: Software Development :: Embedded Systems
21
+ Classifier: Topic :: Software Development :: Libraries
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.11
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSES/MIT.txt
26
+ Requires-Dist: asyncua<3,>=2.0.1
27
+ Requires-Dist: structlog>=26
28
+ Requires-Dist: typing-extensions>=4.16.0
29
+ Provides-Extra: rich
30
+ Requires-Dist: rich>=15.0.0; extra == "rich"
31
+ Requires-Dist: colorama>=0.4; sys_platform == "win32" and extra == "rich"
32
+ Provides-Extra: json
33
+ Requires-Dist: orjson<4,>=3; extra == "json"
34
+ Dynamic: license-file
35
+
36
+ ![OpenSMI Logo](https://smartfactory.de/wp-content/uploads/2026/09/Logo_OpenSMI.png)
37
+
38
+ [![Docs](https://img.shields.io/badge/docs-online-blue)](https://smartfactory-kl.github.io/opensmi-core/)
39
+ [![PyPI version](https://img.shields.io/pypi/v/opensmi-core.svg)](https://pypi.org/project/opensmi-core/)
40
+ [![Python versions](https://img.shields.io/pypi/pyversions/opensmi-core.svg)](https://pypi.org/project/opensmi-core/)
41
+ [![License](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
42
+
43
+ # OpenSMI Core
44
+
45
+ Core functionality for other OpenSMI packages such as:
46
+
47
+ - [OpenSMI Client](https://github.com/SmartFactory-KL/opensmi-client)
48
+ - [OpenSMI Server](https://github.com/SmartFactory-KL/opensmi-server)
49
+
50
+ ## Features
51
+
52
+ - (Nested) Configuration parsing into dataclasses from TOML files (See [config.py](src/opensmi/core/config.py))
53
+ - Lifecycle management via mixin and `@lifecycle` decorators, allowing explicit ordering
54
+ (See [lifecycle_mixin.py](src/opensmi/core/lifecycle_mixin.py))
55
+ - Simple callbacks via `Signal` (similar to [aiosignal](https://pypi.org/project/aiosignal/), but without freezing)
56
+ (See [signal.py](src/opensmi/core/signal.py))
57
+ - [asyncua](https://pypi.org/project/asyncua/) (OPC UA) helpers
58
+ - Node helper functions (See [ua_node_util.py](src/opensmi/core/ua_node_util.py))
59
+ - SubscriptionManager (See [subscription_manager.py](src/opensmi/core/subscription_manager.py))
60
+ - Enums for OpenSMI machine, component and skill states
61
+ - All [UN/CEFACT-Rec20](https://unece.org/trade/documents/2021/06/uncefact-rec20-0) units as a type-checkable enum.
62
+ (See [unit_all.py](src/opensmi/core/unit_all.py))
63
+ - [Structured Logging](https://pypi.org/project/structlog/) configuration (See [logging.py](src/opensmi/core/logging.py))
64
+
65
+ > [!warning]
66
+ > This library is currently pre-1.0 — expect refactoring outside above-mentioned functionality.
67
+
68
+ ## Installation
69
+
70
+ Requires Python 3.11+.
71
+
72
+ ```bash
73
+ pip install opensmi-core
74
+ ```
75
+
76
+ ## Project Status
77
+
78
+ OpenSMI began as a closed-source project at [SmartFactory-KL](https://smartfactory.de/), in active use in our model
79
+ factory since 2020. Its OPC UA information model has been refined across many iterations of research and
80
+ demonstrator use. The framework was open-sourced in 2026 following substantial refactoring and cleanup.
81
+
82
+ ## License
83
+
84
+ [MIT License](LICENSE)
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "0.3",
3
+ "distance": 0,
4
+ "node": "g9a34c7edc8c3a53e37ec1e87441c3e25c2626982",
5
+ "dirty": false,
6
+ "branch": "HEAD",
7
+ "node_date": "2026-10-07"
8
+ }
@@ -4,10 +4,13 @@
4
4
 
5
5
  from __future__ import annotations
6
6
 
7
+ import asyncio
7
8
  import contextlib
9
+ import time
8
10
  from abc import ABC, abstractmethod
11
+ from asyncio import Task
9
12
  from collections.abc import Iterable
10
- from typing import Any
13
+ from typing import Any, Never
11
14
 
12
15
  import structlog
13
16
  from asyncua import ua
@@ -46,49 +49,74 @@ class SubscriptionManager:
46
49
  _ua_client: Client
47
50
  _ua_subscription: Subscription
48
51
 
49
- def __init__(self) -> None:
50
- """Create a new instance."""
52
+ def __init__(
53
+ self,
54
+ *,
55
+ ua_client: Client,
56
+ publishing_interval_ms: float = 100,
57
+ heartbeat_stale_after: float = 10.0,
58
+ ) -> None:
59
+ """Create a new instance.
60
+
61
+ :param ua_client: OPC UA client to use.
62
+ :param publishing_interval_ms: Publishing interval in milliseconds for OPC UA subscription
63
+ :param heartbeat_stale_after: Time in seconds until any subscription should be received.
64
+ """
65
+ self._publishing_interval_ms = publishing_interval_ms
66
+ self._ua_client = ua_client
67
+
51
68
  self._data_subscription_map: dict[NodeId, list[UaDataChangeSubscriber]] = {}
52
69
  """ Maps a OPC UA node to a list of handlers for data change notifications. """
53
70
  self._event_subscription_map: dict[NodeId, list[UaEventSubscriber]] = {}
54
71
  """ Maps a OPC UA node to a list of handlers for event notifications. """
55
72
 
56
- self.period: float = 100
57
- """Publishing interval in milliseconds for OPC UA subscription."""
73
+ self._heartbeat_task: Task[Never] | None = None
74
+ self._last_heartbeat = time.monotonic()
75
+ self._heartbeat_stale_after = heartbeat_stale_after
58
76
 
59
77
  self.logger = structlog.getLogger("opensmi.SubscriptionManager")
60
78
 
61
- async def _create_subscription(self, ua_client: Client):
62
- self._ua_subscription = await ua_client.create_subscription(period=self.period, handler=self)
79
+ async def _create_subscription(self) -> None:
80
+ self._ua_subscription = await self._ua_client.create_subscription(
81
+ period=self._publishing_interval_ms, handler=self
82
+ )
63
83
  self.logger.info("Created subscription!", parameters=self._ua_subscription.parameters)
64
84
 
65
- async def init(self, ua_client: Client, period: float = 100) -> None:
66
- self.period = period
67
- self._ua_client = ua_client
68
- await self._create_subscription(ua_client)
85
+ async def init(self) -> None:
86
+ await self._create_subscription()
69
87
 
70
88
  # subscribe to a node that always changes reliably, for example the current time of the server
71
89
  # this is done to prevent the subscription from timing out
72
- current_time_node = ua_client.get_node(ua.object_ids.ObjectIds.Server_ServerStatus_CurrentTime)
90
+ current_time_node = self._ua_client.get_node(ua.object_ids.ObjectIds.Server_ServerStatus_CurrentTime)
73
91
  await self.subscribe_data_change(self, current_time_node) # pyright: ignore[reportArgumentType]
74
92
 
75
- # async def renew_subscriptions(self, ua_client: Client) -> None:
76
- # self.logger.info(f"Renewing {self.no_of_monitored_items} subscriptions...")
77
- # old_data_subscription_map = self._data_subscription_map.copy()
78
- # old_event_subscription_map = self._event_subscription_map.copy()
79
- #
80
- # await self.clear_subscriptions()
81
- # await self._create_subscription(ua_client)
82
- #
83
- # # add all old data change subscriptions back
84
- # for node_id, handlers in old_data_subscription_map.items():
85
- # for handler in handlers:
86
- # await self.subscribe_data_change(handler=handler, nodes=[ua_client.get_node(node_id)])
87
- #
88
- # # add all old event subscriptions back
89
- # for node_id, handlers in old_event_subscription_map.items():
90
- # for handler in handlers:
91
- # await self.subscribe_event(handler=handler, source_node=node_id)
93
+ self._last_heartbeat = time.monotonic()
94
+ self._heartbeat_task = asyncio.create_task(self._heartbeat_loop(), name="heartbeat_task")
95
+
96
+ async def _renew_subscriptions(self) -> None:
97
+ self.logger.info(f"Trying to renew {self.no_of_monitored_items} subscriptions...")
98
+ old_data_subscription_map = self._data_subscription_map.copy()
99
+ old_event_subscription_map = self._event_subscription_map.copy()
100
+
101
+ await self.clear_subscriptions()
102
+ while True:
103
+ try:
104
+ await self._create_subscription()
105
+ # add all old data change subscriptions back
106
+ for node_id, handlers in old_data_subscription_map.items():
107
+ for handler in handlers:
108
+ await self.subscribe_data_change(handler=handler, nodes=[self._ua_client.get_node(node_id)])
109
+
110
+ # add all old event subscriptions back
111
+ for node_id, handlers in old_event_subscription_map.items():
112
+ for handler in handlers:
113
+ await self.subscribe_event(handler=handler, source_node=node_id)
114
+
115
+ self.logger.info("Successfully renewed subscriptions")
116
+ break
117
+ except Exception as err:
118
+ self.logger.warning("Could not renew subscriptions!", reason=err)
119
+ await asyncio.sleep(1)
92
120
 
93
121
  async def clear_subscriptions(self) -> None:
94
122
  self.logger.info(f"Clearing {self.no_of_monitored_items} subscriptions...")
@@ -160,11 +188,24 @@ class SubscriptionManager:
160
188
  await self._ua_subscription.subscribe_events(sourcenode=source_node)
161
189
  self._event_subscription_map[node_id].append(handler)
162
190
 
191
+ async def _heartbeat_loop(self) -> Never:
192
+ while True:
193
+ await asyncio.sleep(self._heartbeat_stale_after / 4)
194
+ try:
195
+ stale_for = time.monotonic() - self._last_heartbeat
196
+ if stale_for > self._heartbeat_stale_after:
197
+ self.logger.warning("Heartbeat stale, subscriptions presumed dead", stale_for=stale_for)
198
+ await self._renew_subscriptions()
199
+ except Exception as err:
200
+ self.logger.warning("Heartbeat check failed", reason=err)
201
+
163
202
  ###########################################
164
203
  # asyncua callbacks
165
204
 
166
205
  async def datachange_notification(self, node: Node, val: Any, data: DataChangeNotif) -> None:
167
206
  """Handle OPC UA data change notifications callback."""
207
+ self._last_heartbeat = time.monotonic()
208
+
168
209
  try:
169
210
  for handler in self._data_subscription_map[node.nodeid]: # list of handlers
170
211
  if handler == self:
@@ -181,6 +222,8 @@ class SubscriptionManager:
181
222
 
182
223
  async def event_notification(self, ua_event: UaEvent) -> None:
183
224
  """Handle OPC UA event notifications callback."""
225
+ self._last_heartbeat = time.monotonic()
226
+
184
227
  # TODO(CaHa): ua_event.emitting_node is always i=2253 (=Server)
185
228
  # might be an asyncua problem
186
229
  try:
@@ -1,32 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: OpenSMI-Core
3
- Version: 0.2.1
4
- Summary: Smart Machine Interface core functionality for server and client applications.
5
- Author-email: Carsten Harms <Carsten.Harms@dfki.de>, Simon Jungbluth <Simon.Jungbluth@smartfactory.de>
6
- Classifier: Development Status :: 4 - Beta
7
- Classifier: Intended Audience :: Developers
8
- Classifier: Intended Audience :: Information Technology
9
- Classifier: Intended Audience :: Manufacturing
10
- Classifier: Intended Audience :: Science/Research
11
- Classifier: Programming Language :: Python :: 3
12
- Classifier: Programming Language :: Python :: 3.11
13
- Classifier: Programming Language :: Python :: 3.12
14
- Classifier: Programming Language :: Python :: 3.13
15
- Classifier: Programming Language :: Python :: 3.14
16
- Classifier: Topic :: Communications
17
- Classifier: Topic :: Scientific/Engineering
18
- Classifier: Topic :: Scientific/Engineering :: Interface Engine/Protocol Translator
19
- Classifier: Topic :: Software Development :: Embedded Systems
20
- Classifier: Topic :: Software Development :: Libraries
21
- Classifier: Typing :: Typed
22
- Requires-Python: >=3.11
23
- License-File: LICENSE
24
- Requires-Dist: asyncua<3,>=2.0.1
25
- Requires-Dist: structlog>=26
26
- Requires-Dist: typing-extensions>=4.16.0
27
- Provides-Extra: rich
28
- Requires-Dist: rich>=15.0.0; extra == "rich"
29
- Requires-Dist: colorama>=0.4; sys_platform == "win32" and extra == "rich"
30
- Provides-Extra: json
31
- Requires-Dist: orjson<4,>=3; extra == "json"
32
- Dynamic: license-file
@@ -1,32 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: OpenSMI-Core
3
- Version: 0.2.1
4
- Summary: Smart Machine Interface core functionality for server and client applications.
5
- Author-email: Carsten Harms <Carsten.Harms@dfki.de>, Simon Jungbluth <Simon.Jungbluth@smartfactory.de>
6
- Classifier: Development Status :: 4 - Beta
7
- Classifier: Intended Audience :: Developers
8
- Classifier: Intended Audience :: Information Technology
9
- Classifier: Intended Audience :: Manufacturing
10
- Classifier: Intended Audience :: Science/Research
11
- Classifier: Programming Language :: Python :: 3
12
- Classifier: Programming Language :: Python :: 3.11
13
- Classifier: Programming Language :: Python :: 3.12
14
- Classifier: Programming Language :: Python :: 3.13
15
- Classifier: Programming Language :: Python :: 3.14
16
- Classifier: Topic :: Communications
17
- Classifier: Topic :: Scientific/Engineering
18
- Classifier: Topic :: Scientific/Engineering :: Interface Engine/Protocol Translator
19
- Classifier: Topic :: Software Development :: Embedded Systems
20
- Classifier: Topic :: Software Development :: Libraries
21
- Classifier: Typing :: Typed
22
- Requires-Python: >=3.11
23
- License-File: LICENSE
24
- Requires-Dist: asyncua<3,>=2.0.1
25
- Requires-Dist: structlog>=26
26
- Requires-Dist: typing-extensions>=4.16.0
27
- Provides-Extra: rich
28
- Requires-Dist: rich>=15.0.0; extra == "rich"
29
- Requires-Dist: colorama>=0.4; sys_platform == "win32" and extra == "rich"
30
- Provides-Extra: json
31
- Requires-Dist: orjson<4,>=3; extra == "json"
32
- Dynamic: license-file
@@ -1,8 +0,0 @@
1
- {
2
- "tag": "0.2.1",
3
- "distance": 0,
4
- "node": "ga8edabe8cc0987a9434f135a0b149bc312ad6458",
5
- "dirty": false,
6
- "branch": "HEAD",
7
- "node_date": "2026-10-06"
8
- }
File without changes
File without changes
File without changes
File without changes
File without changes