rocket-welder-sdk 1.1.34.dev11__py3-none-any.whl → 1.1.34rc1__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.
- rocket_welder_sdk/__init__.py +1 -20
- rocket_welder_sdk/controllers.py +3 -7
- rocket_welder_sdk/frame_metadata.py +2 -2
- rocket_welder_sdk/high_level/__init__.py +25 -11
- rocket_welder_sdk/high_level/connection_strings.py +55 -56
- rocket_welder_sdk/high_level/data_context.py +11 -17
- rocket_welder_sdk/high_level/schema.py +27 -44
- rocket_welder_sdk/high_level/transport_protocol.py +108 -180
- rocket_welder_sdk/rocket_welder_client.py +14 -34
- rocket_welder_sdk/session_id.py +0 -123
- rocket_welder_sdk/transport/__init__.py +8 -0
- {rocket_welder_sdk-1.1.34.dev11.dist-info → rocket_welder_sdk-1.1.34rc1.dist-info}/METADATA +1 -1
- {rocket_welder_sdk-1.1.34.dev11.dist-info → rocket_welder_sdk-1.1.34rc1.dist-info}/RECORD +15 -16
- rocket_welder_sdk/high_level/client.py +0 -262
- {rocket_welder_sdk-1.1.34.dev11.dist-info → rocket_welder_sdk-1.1.34rc1.dist-info}/WHEEL +0 -0
- {rocket_welder_sdk-1.1.34.dev11.dist-info → rocket_welder_sdk-1.1.34rc1.dist-info}/top_level.txt +0 -0
|
@@ -1,204 +1,103 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
2
|
+
Transport protocol types with composable + operator.
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
file:///home/user/output.bin - absolute file path
|
|
8
|
-
socket:///tmp/my.sock - Unix domain socket
|
|
9
|
-
nng+push+ipc://tmp/keypoints - NNG Push over IPC
|
|
10
|
-
nng+push+tcp://host:5555 - NNG Push over TCP
|
|
4
|
+
Allows building transport protocols like:
|
|
5
|
+
protocol = Transport.Nng + Transport.Push + Transport.Ipc
|
|
6
|
+
# Results in TransportProtocol("nng", "push", "ipc")
|
|
11
7
|
"""
|
|
12
8
|
|
|
13
9
|
from __future__ import annotations
|
|
14
10
|
|
|
15
|
-
from
|
|
16
|
-
from typing import
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
class TransportKind(Enum):
|
|
20
|
-
"""Transport kind enumeration."""
|
|
21
|
-
|
|
22
|
-
FILE = auto()
|
|
23
|
-
"""File output."""
|
|
24
|
-
|
|
25
|
-
SOCKET = auto()
|
|
26
|
-
"""Unix domain socket (direct, no messaging library)."""
|
|
11
|
+
from dataclasses import dataclass
|
|
12
|
+
from typing import Optional
|
|
27
13
|
|
|
28
|
-
NNG_PUSH_IPC = auto()
|
|
29
|
-
"""NNG Push over IPC."""
|
|
30
14
|
|
|
31
|
-
|
|
32
|
-
|
|
15
|
+
@dataclass(frozen=True)
|
|
16
|
+
class MessagingLibrary:
|
|
17
|
+
"""Messaging library (nng, zeromq, etc.)."""
|
|
33
18
|
|
|
34
|
-
|
|
35
|
-
"""NNG Pull over IPC."""
|
|
19
|
+
name: str
|
|
36
20
|
|
|
37
|
-
|
|
38
|
-
|
|
21
|
+
def __add__(self, pattern: MessagingPattern) -> TransportBuilder:
|
|
22
|
+
"""Compose with messaging pattern: Nng + Push."""
|
|
23
|
+
return TransportBuilder(library=self, pattern=pattern)
|
|
39
24
|
|
|
40
|
-
|
|
41
|
-
|
|
25
|
+
def __str__(self) -> str:
|
|
26
|
+
return self.name
|
|
42
27
|
|
|
43
|
-
NNG_PUB_TCP = auto()
|
|
44
|
-
"""NNG Pub over TCP."""
|
|
45
28
|
|
|
46
|
-
|
|
47
|
-
|
|
29
|
+
@dataclass(frozen=True)
|
|
30
|
+
class MessagingPattern:
|
|
31
|
+
"""Messaging pattern (push/pull, pub/sub, etc.)."""
|
|
48
32
|
|
|
49
|
-
|
|
50
|
-
"""NNG Sub over TCP."""
|
|
33
|
+
name: str
|
|
51
34
|
|
|
35
|
+
def __str__(self) -> str:
|
|
36
|
+
return self.name
|
|
52
37
|
|
|
53
|
-
class TransportProtocol:
|
|
54
|
-
"""
|
|
55
|
-
Unified transport protocol specification as a value type.
|
|
56
|
-
|
|
57
|
-
Supports: file://, socket://, nng+push+ipc://, nng+push+tcp://, etc.
|
|
58
|
-
"""
|
|
59
|
-
|
|
60
|
-
# Predefined protocols
|
|
61
|
-
File: TransportProtocol
|
|
62
|
-
Socket: TransportProtocol
|
|
63
|
-
NngPushIpc: TransportProtocol
|
|
64
|
-
NngPushTcp: TransportProtocol
|
|
65
|
-
NngPullIpc: TransportProtocol
|
|
66
|
-
NngPullTcp: TransportProtocol
|
|
67
|
-
NngPubIpc: TransportProtocol
|
|
68
|
-
NngPubTcp: TransportProtocol
|
|
69
|
-
NngSubIpc: TransportProtocol
|
|
70
|
-
NngSubTcp: TransportProtocol
|
|
71
|
-
|
|
72
|
-
_SCHEMA_MAP: ClassVar[Dict[str, TransportKind]] = {
|
|
73
|
-
"file": TransportKind.FILE,
|
|
74
|
-
"socket": TransportKind.SOCKET,
|
|
75
|
-
"nng+push+ipc": TransportKind.NNG_PUSH_IPC,
|
|
76
|
-
"nng+push+tcp": TransportKind.NNG_PUSH_TCP,
|
|
77
|
-
"nng+pull+ipc": TransportKind.NNG_PULL_IPC,
|
|
78
|
-
"nng+pull+tcp": TransportKind.NNG_PULL_TCP,
|
|
79
|
-
"nng+pub+ipc": TransportKind.NNG_PUB_IPC,
|
|
80
|
-
"nng+pub+tcp": TransportKind.NNG_PUB_TCP,
|
|
81
|
-
"nng+sub+ipc": TransportKind.NNG_SUB_IPC,
|
|
82
|
-
"nng+sub+tcp": TransportKind.NNG_SUB_TCP,
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
_KIND_TO_SCHEMA: ClassVar[Dict[TransportKind, str]] = {}
|
|
86
|
-
|
|
87
|
-
def __init__(self, kind: TransportKind, schema: str) -> None:
|
|
88
|
-
self._kind = kind
|
|
89
|
-
self._schema = schema
|
|
90
38
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
return self._kind
|
|
39
|
+
@dataclass(frozen=True)
|
|
40
|
+
class TransportLayer:
|
|
41
|
+
"""Transport layer (ipc, tcp, etc.)."""
|
|
95
42
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
"""The schema string (e.g., 'file', 'socket', 'nng+push+ipc')."""
|
|
99
|
-
return self._schema
|
|
43
|
+
name: str
|
|
44
|
+
uri_prefix: str
|
|
100
45
|
|
|
101
|
-
|
|
46
|
+
def __str__(self) -> str:
|
|
47
|
+
return self.name
|
|
102
48
|
|
|
103
|
-
@property
|
|
104
|
-
def is_file(self) -> bool:
|
|
105
|
-
"""True if this is a file transport."""
|
|
106
|
-
return self._kind == TransportKind.FILE
|
|
107
49
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
return self._kind == TransportKind.SOCKET
|
|
50
|
+
@dataclass(frozen=True)
|
|
51
|
+
class TransportBuilder:
|
|
52
|
+
"""Builder for constructing transport protocols."""
|
|
112
53
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
"""True if this is any NNG-based transport."""
|
|
116
|
-
return self._kind in {
|
|
117
|
-
TransportKind.NNG_PUSH_IPC,
|
|
118
|
-
TransportKind.NNG_PUSH_TCP,
|
|
119
|
-
TransportKind.NNG_PULL_IPC,
|
|
120
|
-
TransportKind.NNG_PULL_TCP,
|
|
121
|
-
TransportKind.NNG_PUB_IPC,
|
|
122
|
-
TransportKind.NNG_PUB_TCP,
|
|
123
|
-
TransportKind.NNG_SUB_IPC,
|
|
124
|
-
TransportKind.NNG_SUB_TCP,
|
|
125
|
-
}
|
|
54
|
+
library: MessagingLibrary
|
|
55
|
+
pattern: MessagingPattern
|
|
126
56
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
return self._kind in {TransportKind.NNG_PUSH_IPC, TransportKind.NNG_PUSH_TCP}
|
|
57
|
+
def __add__(self, layer: TransportLayer) -> TransportProtocol:
|
|
58
|
+
"""Compose with transport layer: (Nng + Push) + Ipc."""
|
|
59
|
+
return TransportProtocol(library=self.library, pattern=self.pattern, layer=layer)
|
|
131
60
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
"""True if this is a Pull pattern."""
|
|
135
|
-
return self._kind in {TransportKind.NNG_PULL_IPC, TransportKind.NNG_PULL_TCP}
|
|
61
|
+
def __str__(self) -> str:
|
|
62
|
+
return f"{self.library}+{self.pattern}"
|
|
136
63
|
|
|
137
|
-
@property
|
|
138
|
-
def is_pub(self) -> bool:
|
|
139
|
-
"""True if this is a Pub pattern."""
|
|
140
|
-
return self._kind in {TransportKind.NNG_PUB_IPC, TransportKind.NNG_PUB_TCP}
|
|
141
64
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
return self._kind in {TransportKind.NNG_SUB_IPC, TransportKind.NNG_SUB_TCP}
|
|
65
|
+
@dataclass(frozen=True)
|
|
66
|
+
class TransportProtocol:
|
|
67
|
+
"""Complete transport protocol specification."""
|
|
146
68
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
return self._kind in {
|
|
151
|
-
TransportKind.NNG_PUSH_IPC,
|
|
152
|
-
TransportKind.NNG_PULL_IPC,
|
|
153
|
-
TransportKind.NNG_PUB_IPC,
|
|
154
|
-
TransportKind.NNG_SUB_IPC,
|
|
155
|
-
}
|
|
69
|
+
library: MessagingLibrary
|
|
70
|
+
pattern: MessagingPattern
|
|
71
|
+
layer: TransportLayer
|
|
156
72
|
|
|
157
73
|
@property
|
|
158
|
-
def
|
|
159
|
-
"""
|
|
160
|
-
return self.
|
|
161
|
-
TransportKind.NNG_PUSH_TCP,
|
|
162
|
-
TransportKind.NNG_PULL_TCP,
|
|
163
|
-
TransportKind.NNG_PUB_TCP,
|
|
164
|
-
TransportKind.NNG_SUB_TCP,
|
|
165
|
-
}
|
|
74
|
+
def protocol_string(self) -> str:
|
|
75
|
+
"""Protocol string for parsing (e.g., 'nng+push+ipc')."""
|
|
76
|
+
return f"{self.library}+{self.pattern}+{self.layer}"
|
|
166
77
|
|
|
167
78
|
def create_nng_address(self, path_or_host: str) -> str:
|
|
168
79
|
"""
|
|
169
80
|
Create the NNG address from a path/host.
|
|
170
81
|
|
|
171
|
-
For IPC:
|
|
172
|
-
For TCP:
|
|
173
|
-
|
|
174
|
-
Raises:
|
|
175
|
-
ValueError: If this is not an NNG protocol.
|
|
82
|
+
For IPC: adds leading "/" to make absolute path
|
|
83
|
+
For TCP: uses as-is
|
|
176
84
|
"""
|
|
177
|
-
if not
|
|
178
|
-
|
|
85
|
+
if self.layer == Transport.Ipc and not path_or_host.startswith("/"):
|
|
86
|
+
return f"{self.layer.uri_prefix}/{path_or_host}"
|
|
87
|
+
return f"{self.layer.uri_prefix}{path_or_host}"
|
|
179
88
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
return f"ipc://{path_or_host}"
|
|
89
|
+
@property
|
|
90
|
+
def is_push(self) -> bool:
|
|
91
|
+
"""Check if this is a push pattern."""
|
|
92
|
+
return self.pattern == Transport.Push
|
|
185
93
|
|
|
186
|
-
|
|
187
|
-
|
|
94
|
+
@property
|
|
95
|
+
def is_pub(self) -> bool:
|
|
96
|
+
"""Check if this is a pub pattern."""
|
|
97
|
+
return self.pattern == Transport.Pub
|
|
188
98
|
|
|
189
99
|
def __str__(self) -> str:
|
|
190
|
-
return self.
|
|
191
|
-
|
|
192
|
-
def __repr__(self) -> str:
|
|
193
|
-
return f"TransportProtocol({self._kind.name}, '{self._schema}')"
|
|
194
|
-
|
|
195
|
-
def __eq__(self, other: object) -> bool:
|
|
196
|
-
if isinstance(other, TransportProtocol):
|
|
197
|
-
return self._kind == other._kind
|
|
198
|
-
return False
|
|
199
|
-
|
|
200
|
-
def __hash__(self) -> int:
|
|
201
|
-
return hash(self._kind)
|
|
100
|
+
return self.protocol_string
|
|
202
101
|
|
|
203
102
|
@classmethod
|
|
204
103
|
def parse(cls, s: str) -> TransportProtocol:
|
|
@@ -209,30 +108,59 @@ class TransportProtocol:
|
|
|
209
108
|
return result
|
|
210
109
|
|
|
211
110
|
@classmethod
|
|
212
|
-
def try_parse(cls, s:
|
|
111
|
+
def try_parse(cls, s: str) -> Optional[TransportProtocol]:
|
|
213
112
|
"""Try to parse a protocol string."""
|
|
214
113
|
if not s:
|
|
215
114
|
return None
|
|
216
115
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
116
|
+
parts = s.lower().split("+")
|
|
117
|
+
if len(parts) != 3:
|
|
118
|
+
return None
|
|
119
|
+
|
|
120
|
+
# Parse library
|
|
121
|
+
if parts[0] == "nng":
|
|
122
|
+
library = Transport.Nng
|
|
123
|
+
else:
|
|
124
|
+
return None
|
|
125
|
+
|
|
126
|
+
# Parse pattern
|
|
127
|
+
if parts[1] == "push":
|
|
128
|
+
pattern = Transport.Push
|
|
129
|
+
elif parts[1] == "pull":
|
|
130
|
+
pattern = Transport.Pull
|
|
131
|
+
elif parts[1] == "pub":
|
|
132
|
+
pattern = Transport.Pub
|
|
133
|
+
elif parts[1] == "sub":
|
|
134
|
+
pattern = Transport.Sub
|
|
135
|
+
else:
|
|
220
136
|
return None
|
|
221
137
|
|
|
222
|
-
|
|
138
|
+
# Parse layer
|
|
139
|
+
if parts[2] == "ipc":
|
|
140
|
+
layer = Transport.Ipc
|
|
141
|
+
elif parts[2] == "tcp":
|
|
142
|
+
layer = Transport.Tcp
|
|
143
|
+
else:
|
|
144
|
+
return None
|
|
145
|
+
|
|
146
|
+
return cls(library=library, pattern=pattern, layer=layer)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
class Transport:
|
|
150
|
+
"""Static helpers for building transport protocols using + operator."""
|
|
151
|
+
|
|
152
|
+
# Messaging libraries
|
|
153
|
+
Nng: MessagingLibrary = MessagingLibrary("nng")
|
|
223
154
|
|
|
155
|
+
# Messaging patterns
|
|
156
|
+
Push: MessagingPattern = MessagingPattern("push")
|
|
157
|
+
Pull: MessagingPattern = MessagingPattern("pull")
|
|
158
|
+
Pub: MessagingPattern = MessagingPattern("pub")
|
|
159
|
+
Sub: MessagingPattern = MessagingPattern("sub")
|
|
224
160
|
|
|
225
|
-
#
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
TransportProtocol.NngPushIpc = TransportProtocol(TransportKind.NNG_PUSH_IPC, "nng+push+ipc")
|
|
229
|
-
TransportProtocol.NngPushTcp = TransportProtocol(TransportKind.NNG_PUSH_TCP, "nng+push+tcp")
|
|
230
|
-
TransportProtocol.NngPullIpc = TransportProtocol(TransportKind.NNG_PULL_IPC, "nng+pull+ipc")
|
|
231
|
-
TransportProtocol.NngPullTcp = TransportProtocol(TransportKind.NNG_PULL_TCP, "nng+pull+tcp")
|
|
232
|
-
TransportProtocol.NngPubIpc = TransportProtocol(TransportKind.NNG_PUB_IPC, "nng+pub+ipc")
|
|
233
|
-
TransportProtocol.NngPubTcp = TransportProtocol(TransportKind.NNG_PUB_TCP, "nng+pub+tcp")
|
|
234
|
-
TransportProtocol.NngSubIpc = TransportProtocol(TransportKind.NNG_SUB_IPC, "nng+sub+ipc")
|
|
235
|
-
TransportProtocol.NngSubTcp = TransportProtocol(TransportKind.NNG_SUB_TCP, "nng+sub+tcp")
|
|
161
|
+
# Transport layers
|
|
162
|
+
Ipc: TransportLayer = TransportLayer("ipc", "ipc://")
|
|
163
|
+
Tcp: TransportLayer = TransportLayer("tcp", "tcp://")
|
|
236
164
|
|
|
237
|
-
#
|
|
238
|
-
|
|
165
|
+
# File output (not a real transport)
|
|
166
|
+
File: str = "file"
|
|
@@ -16,11 +16,7 @@ from .connection_string import ConnectionMode, ConnectionString, Protocol
|
|
|
16
16
|
from .controllers import DuplexShmController, IController, OneWayShmController
|
|
17
17
|
from .frame_metadata import FrameMetadata # noqa: TC001 - used at runtime in callbacks
|
|
18
18
|
from .opencv_controller import OpenCvController
|
|
19
|
-
from .session_id import
|
|
20
|
-
get_configured_nng_urls,
|
|
21
|
-
get_nng_urls_from_env,
|
|
22
|
-
has_explicit_nng_urls,
|
|
23
|
-
)
|
|
19
|
+
from .session_id import get_nng_urls, get_session_id_from_env
|
|
24
20
|
from .transport.nng_transport import NngFrameSink
|
|
25
21
|
|
|
26
22
|
if TYPE_CHECKING:
|
|
@@ -94,33 +90,27 @@ class RocketWelderClient:
|
|
|
94
90
|
"""
|
|
95
91
|
return self._nng_publishers
|
|
96
92
|
|
|
97
|
-
def _create_nng_publishers(self) -> None:
|
|
93
|
+
def _create_nng_publishers(self, session_id: str) -> None:
|
|
98
94
|
"""Create NNG publishers for result streaming.
|
|
99
95
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
Priority:
|
|
103
|
-
1. Explicit URLs: SEGMENTATION_SINK_URL, KEYPOINTS_SINK_URL, ACTIONS_SINK_URL
|
|
104
|
-
2. Derived from SessionId environment variable (backwards compatibility)
|
|
96
|
+
Args:
|
|
97
|
+
session_id: SessionId string (e.g., "ps-{guid}")
|
|
105
98
|
"""
|
|
106
99
|
try:
|
|
107
|
-
urls =
|
|
100
|
+
urls = get_nng_urls(session_id)
|
|
108
101
|
|
|
109
102
|
for name, url in urls.items():
|
|
110
103
|
sink = NngFrameSink.create_publisher(url)
|
|
111
104
|
self._nng_publishers[name] = sink
|
|
112
105
|
logger.info("NNG publisher ready: %s at %s", name, url)
|
|
113
106
|
|
|
114
|
-
# Log configuration summary
|
|
115
107
|
logger.info(
|
|
116
|
-
"NNG publishers
|
|
117
|
-
|
|
118
|
-
urls
|
|
119
|
-
urls
|
|
108
|
+
"NNG publishers created for SessionId=%s: seg=%s, kp=%s, actions=%s",
|
|
109
|
+
session_id,
|
|
110
|
+
urls["segmentation"],
|
|
111
|
+
urls["keypoints"],
|
|
112
|
+
urls["actions"],
|
|
120
113
|
)
|
|
121
|
-
except ValueError as ex:
|
|
122
|
-
# No URLs configured - this is expected for containers that don't publish results
|
|
123
|
-
logger.debug("NNG publishers not configured: %s", ex)
|
|
124
114
|
except Exception as ex:
|
|
125
115
|
logger.warning("Failed to create NNG publishers: %s", ex)
|
|
126
116
|
# Don't fail start() - NNG is optional for backwards compatibility
|
|
@@ -172,20 +162,10 @@ class RocketWelderClient:
|
|
|
172
162
|
else:
|
|
173
163
|
raise ValueError(f"Unsupported protocol: {self._connection.protocol}")
|
|
174
164
|
|
|
175
|
-
# Auto-create NNG publishers if
|
|
176
|
-
|
|
177
|
-
if
|
|
178
|
-
self._create_nng_publishers()
|
|
179
|
-
else:
|
|
180
|
-
# Log that NNG is not configured (informational)
|
|
181
|
-
urls = get_nng_urls_from_env()
|
|
182
|
-
logger.info(
|
|
183
|
-
"NNG sink URLs not configured (this is normal if not publishing AI results). "
|
|
184
|
-
"seg=%s, kp=%s, actions=%s",
|
|
185
|
-
urls.get("segmentation") or "(not set)",
|
|
186
|
-
urls.get("keypoints") or "(not set)",
|
|
187
|
-
urls.get("actions") or "(not set)",
|
|
188
|
-
)
|
|
165
|
+
# Auto-create NNG publishers if SessionId env var is set
|
|
166
|
+
session_id = get_session_id_from_env()
|
|
167
|
+
if session_id:
|
|
168
|
+
self._create_nng_publishers(session_id)
|
|
189
169
|
|
|
190
170
|
# If preview is enabled, wrap the callback to capture frames
|
|
191
171
|
if self._preview_enabled:
|
rocket_welder_sdk/session_id.py
CHANGED
|
@@ -7,22 +7,6 @@ This module provides utilities to:
|
|
|
7
7
|
1. Parse SessionId from environment variable
|
|
8
8
|
2. Extract the Guid portion
|
|
9
9
|
3. Generate NNG IPC URLs for streaming results
|
|
10
|
-
4. Read explicit NNG URLs from environment variables (preferred)
|
|
11
|
-
|
|
12
|
-
## URL Configuration Priority
|
|
13
|
-
|
|
14
|
-
The SDK supports two ways to configure NNG URLs:
|
|
15
|
-
|
|
16
|
-
1. **Explicit URLs (PREFERRED)** - Set by rocket-welder2:
|
|
17
|
-
- SEGMENTATION_SINK_URL
|
|
18
|
-
- KEYPOINTS_SINK_URL
|
|
19
|
-
- ACTIONS_SINK_URL
|
|
20
|
-
|
|
21
|
-
2. **Derived from SessionId (FALLBACK)** - For backwards compatibility:
|
|
22
|
-
- SessionId env var → parse GUID → generate URLs
|
|
23
|
-
|
|
24
|
-
Use `get_nng_urls_from_env()` for explicit URLs (preferred).
|
|
25
|
-
Use `get_nng_urls(session_id)` for SessionId-derived URLs (fallback).
|
|
26
10
|
"""
|
|
27
11
|
|
|
28
12
|
from __future__ import annotations
|
|
@@ -36,11 +20,6 @@ logger = logging.getLogger(__name__)
|
|
|
36
20
|
SESSION_ID_PREFIX = "ps-"
|
|
37
21
|
SESSION_ID_ENV_VAR = "SessionId"
|
|
38
22
|
|
|
39
|
-
# Explicit URL environment variables (set by rocket-welder2)
|
|
40
|
-
SEGMENTATION_SINK_URL_ENV = "SEGMENTATION_SINK_URL"
|
|
41
|
-
KEYPOINTS_SINK_URL_ENV = "KEYPOINTS_SINK_URL"
|
|
42
|
-
ACTIONS_SINK_URL_ENV = "ACTIONS_SINK_URL"
|
|
43
|
-
|
|
44
23
|
|
|
45
24
|
def parse_session_id(session_id: str) -> uuid.UUID:
|
|
46
25
|
"""Parse SessionId (ps-{guid}) to extract Guid.
|
|
@@ -134,105 +113,3 @@ def get_actions_url(session_id: str) -> str:
|
|
|
134
113
|
"""
|
|
135
114
|
guid = parse_session_id(session_id)
|
|
136
115
|
return f"ipc:///tmp/rw-{guid}-actions.sock"
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
# ============================================================================
|
|
140
|
-
# Explicit URL functions (PREFERRED - URLs set by rocket-welder2)
|
|
141
|
-
# ============================================================================
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
def get_nng_urls_from_env() -> dict[str, str | None]:
|
|
145
|
-
"""Get NNG URLs from explicit environment variables.
|
|
146
|
-
|
|
147
|
-
This is the PREFERRED method for getting NNG URLs. rocket-welder2
|
|
148
|
-
sets these environment variables when starting containers.
|
|
149
|
-
|
|
150
|
-
Returns:
|
|
151
|
-
Dictionary with 'segmentation', 'keypoints', 'actions' URLs.
|
|
152
|
-
Values are None if not configured.
|
|
153
|
-
|
|
154
|
-
Examples:
|
|
155
|
-
>>> os.environ["SEGMENTATION_SINK_URL"] = "ipc:///tmp/rw-abc-seg.sock"
|
|
156
|
-
>>> urls = get_nng_urls_from_env()
|
|
157
|
-
>>> urls["segmentation"]
|
|
158
|
-
'ipc:///tmp/rw-abc-seg.sock'
|
|
159
|
-
"""
|
|
160
|
-
return {
|
|
161
|
-
"segmentation": os.environ.get(SEGMENTATION_SINK_URL_ENV),
|
|
162
|
-
"keypoints": os.environ.get(KEYPOINTS_SINK_URL_ENV),
|
|
163
|
-
"actions": os.environ.get(ACTIONS_SINK_URL_ENV),
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
def get_segmentation_url_from_env() -> str | None:
|
|
168
|
-
"""Get segmentation NNG URL from environment variable.
|
|
169
|
-
|
|
170
|
-
Returns:
|
|
171
|
-
IPC URL for segmentation stream, or None if not configured.
|
|
172
|
-
"""
|
|
173
|
-
return os.environ.get(SEGMENTATION_SINK_URL_ENV)
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
def get_keypoints_url_from_env() -> str | None:
|
|
177
|
-
"""Get keypoints NNG URL from environment variable.
|
|
178
|
-
|
|
179
|
-
Returns:
|
|
180
|
-
IPC URL for keypoints stream, or None if not configured.
|
|
181
|
-
"""
|
|
182
|
-
return os.environ.get(KEYPOINTS_SINK_URL_ENV)
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
def get_actions_url_from_env() -> str | None:
|
|
186
|
-
"""Get actions NNG URL from environment variable.
|
|
187
|
-
|
|
188
|
-
Returns:
|
|
189
|
-
IPC URL for actions stream, or None if not configured.
|
|
190
|
-
"""
|
|
191
|
-
return os.environ.get(ACTIONS_SINK_URL_ENV)
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
def has_explicit_nng_urls() -> bool:
|
|
195
|
-
"""Check if explicit NNG URLs are configured.
|
|
196
|
-
|
|
197
|
-
Returns:
|
|
198
|
-
True if at least segmentation OR keypoints URL is configured.
|
|
199
|
-
"""
|
|
200
|
-
urls = get_nng_urls_from_env()
|
|
201
|
-
return bool(urls["segmentation"] or urls["keypoints"])
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
def get_configured_nng_urls() -> dict[str, str]:
|
|
205
|
-
"""Get all configured NNG URLs (explicit or derived from SessionId).
|
|
206
|
-
|
|
207
|
-
Priority:
|
|
208
|
-
1. Explicit URLs from environment (SEGMENTATION_SINK_URL, etc.)
|
|
209
|
-
2. Derived from SessionId environment variable (fallback)
|
|
210
|
-
|
|
211
|
-
Returns:
|
|
212
|
-
Dictionary with 'segmentation', 'keypoints', 'actions' URLs.
|
|
213
|
-
Only includes URLs that are actually configured.
|
|
214
|
-
|
|
215
|
-
Raises:
|
|
216
|
-
ValueError: If no NNG URLs are configured (neither explicit nor SessionId).
|
|
217
|
-
"""
|
|
218
|
-
# Try explicit URLs first (preferred)
|
|
219
|
-
explicit_urls = get_nng_urls_from_env()
|
|
220
|
-
result: dict[str, str] = {}
|
|
221
|
-
|
|
222
|
-
for name, url in explicit_urls.items():
|
|
223
|
-
if url:
|
|
224
|
-
result[name] = url
|
|
225
|
-
|
|
226
|
-
# If we have at least one explicit URL, return what we have
|
|
227
|
-
if result:
|
|
228
|
-
return result
|
|
229
|
-
|
|
230
|
-
# Fallback: derive from SessionId
|
|
231
|
-
session_id = get_session_id_from_env()
|
|
232
|
-
if session_id:
|
|
233
|
-
return get_nng_urls(session_id)
|
|
234
|
-
|
|
235
|
-
raise ValueError(
|
|
236
|
-
"No NNG URLs configured. Set SEGMENTATION_SINK_URL/KEYPOINTS_SINK_URL "
|
|
237
|
-
"environment variables, or set SessionId for URL derivation."
|
|
238
|
-
)
|
|
@@ -28,3 +28,11 @@ __all__ = [
|
|
|
28
28
|
"UnixSocketFrameSource",
|
|
29
29
|
"UnixSocketServer",
|
|
30
30
|
]
|
|
31
|
+
|
|
32
|
+
# NNG transport is optional (requires pynng package)
|
|
33
|
+
try:
|
|
34
|
+
from .nng_transport import NngFrameSink, NngFrameSource
|
|
35
|
+
|
|
36
|
+
__all__.extend(["NngFrameSink", "NngFrameSource"])
|
|
37
|
+
except ImportError:
|
|
38
|
+
pass # pynng not installed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rocket-welder-sdk
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.34rc1
|
|
4
4
|
Summary: High-performance video streaming SDK for RocketWelder services using ZeroBuffer IPC
|
|
5
5
|
Home-page: https://github.com/modelingevolution/rocket-welder-sdk
|
|
6
6
|
Author: ModelingEvolution
|
|
@@ -1,26 +1,25 @@
|
|
|
1
|
-
rocket_welder_sdk/__init__.py,sha256=
|
|
1
|
+
rocket_welder_sdk/__init__.py,sha256=7jawqof-tt0S0G7CMMOmHRsVLbUf-o8sSREP1VxEeJ4,2400
|
|
2
2
|
rocket_welder_sdk/bytes_size.py,sha256=Myl29-wyWCIYdbMmgaxXebT8Dz8_Fwcr3fnfaNW81P0,7463
|
|
3
3
|
rocket_welder_sdk/connection_string.py,sha256=NIC6OiOXF-DeBFCWzgMFOWsenrSS45hY81j_HLMSpgo,9974
|
|
4
|
-
rocket_welder_sdk/controllers.py,sha256=
|
|
5
|
-
rocket_welder_sdk/frame_metadata.py,sha256=
|
|
4
|
+
rocket_welder_sdk/controllers.py,sha256=X7D7OyiuHhGTrmrSNG2Tljsy1_4PGRObytB4dLyvRrg,32600
|
|
5
|
+
rocket_welder_sdk/frame_metadata.py,sha256=8AbCgSQ17QeCHSzdQiSN0E1KxE5rrNpOlTYZ2em8kes,3903
|
|
6
6
|
rocket_welder_sdk/gst_metadata.py,sha256=jEQvZX4BdR6OR3lqp12PV-HEXZhcxfiS010diA2CbMM,14213
|
|
7
7
|
rocket_welder_sdk/keypoints_protocol.py,sha256=NKiSPrevWG4_RrD6jtFxPjwftlaPWe1CqoFVKRMwp4k,21858
|
|
8
8
|
rocket_welder_sdk/opencv_controller.py,sha256=MDM6_yFBB9BaMa5jnZRqw7xZZB-WuLr7EPrrfHQ2DK4,9905
|
|
9
9
|
rocket_welder_sdk/periodic_timer.py,sha256=hnObybmrnf3J47QrNKJhYAytLKwria016123NvPRfQ0,9369
|
|
10
10
|
rocket_welder_sdk/py.typed,sha256=0cXFZXmes4Y-vnl4lO3HtyyyWaFNw85B7tJdFeCtHDc,67
|
|
11
|
-
rocket_welder_sdk/rocket_welder_client.py,sha256=
|
|
11
|
+
rocket_welder_sdk/rocket_welder_client.py,sha256=2tGL98hLXU_Xl2LzjhdLpQkp9oxzb4D3WmPOcMZMyw4,17474
|
|
12
12
|
rocket_welder_sdk/segmentation_result.py,sha256=q3n8m1sooPcattfXisL9em5gZKbEZ1ueGqeXfOrdaHY,13417
|
|
13
|
-
rocket_welder_sdk/session_id.py,sha256=
|
|
13
|
+
rocket_welder_sdk/session_id.py,sha256=4RVNxuMzJsJ3Me1LveTe_RSDevEUsOozlamSRMXfXGA,3114
|
|
14
14
|
rocket_welder_sdk/external_controls/__init__.py,sha256=ldOLGhLLS5BQL8m4VKFYV0SvsNNlV2tghlc7rkqadU8,699
|
|
15
15
|
rocket_welder_sdk/external_controls/contracts.py,sha256=3DU6pdpteN50gF2fsS7C2279dGjDa0tZLrLntkBa2LM,2607
|
|
16
16
|
rocket_welder_sdk/external_controls/contracts_old.py,sha256=XWriuXJZu5caTSS0bcTIOZcKnj-IRCm96voA4gqLBfU,2980
|
|
17
|
-
rocket_welder_sdk/high_level/__init__.py,sha256=
|
|
18
|
-
rocket_welder_sdk/high_level/
|
|
19
|
-
rocket_welder_sdk/high_level/
|
|
20
|
-
rocket_welder_sdk/high_level/
|
|
21
|
-
rocket_welder_sdk/high_level/
|
|
22
|
-
rocket_welder_sdk/
|
|
23
|
-
rocket_welder_sdk/transport/__init__.py,sha256=DYmZpohGPU7RhS6EdVT_BwCy5MZzyTQ6Eymm8TpmxJ8,751
|
|
17
|
+
rocket_welder_sdk/high_level/__init__.py,sha256=5oTCBL2qMGonCytHDckmX1b1U97-7Xb8Bg9Z70nR7fc,1759
|
|
18
|
+
rocket_welder_sdk/high_level/connection_strings.py,sha256=4undnkbWZ837vY-o6ybIj1827F2VlUbCJX4m3Filz-s,10469
|
|
19
|
+
rocket_welder_sdk/high_level/data_context.py,sha256=Pmwsl9MgBfKA9BqmBJmAVRvnaqPdjnq2rZEA_pzzYsw,4585
|
|
20
|
+
rocket_welder_sdk/high_level/schema.py,sha256=UlefNAV2UL9eO_Th2q19a7tf_eoaeLE92fYZ5LNq7-M,4849
|
|
21
|
+
rocket_welder_sdk/high_level/transport_protocol.py,sha256=lvLVHikW_MNZhXqaXlyXscT68OklyMbGs8DnDEMCtgE,4515
|
|
22
|
+
rocket_welder_sdk/transport/__init__.py,sha256=L-wl0YWhVbSrof94Zt4g7SIM-wTPzujdVOsEfJHiJT4,978
|
|
24
23
|
rocket_welder_sdk/transport/frame_sink.py,sha256=16dUefZF1QJv62Ig0ezPR6nEho_7A3WJu4M9_PPMqJM,2164
|
|
25
24
|
rocket_welder_sdk/transport/frame_source.py,sha256=G1rBAQS1AgOOdtASB0_CYon8g20hUGXpP2exCp5hlhk,2169
|
|
26
25
|
rocket_welder_sdk/transport/nng_transport.py,sha256=o-qgcmHCGnwtdPe-mwwrC-a9H0rgS-VdH2QvU-6kFlI,5838
|
|
@@ -33,7 +32,7 @@ rocket_welder_sdk/ui/icons.py,sha256=DcDklZkPmiEzlOD4IR7VTJOtGPCuuh_OM_WN7ScghWE
|
|
|
33
32
|
rocket_welder_sdk/ui/ui_events_projection.py,sha256=siiNhjLEBOPfTKw1ZhOPGkwIN5rLDH7V9VCZTNrhEtQ,7836
|
|
34
33
|
rocket_welder_sdk/ui/ui_service.py,sha256=uRdpyJGoCQmtOli_HKSrxLwhZYG-XRuHIYdkmFz1zNk,12026
|
|
35
34
|
rocket_welder_sdk/ui/value_types.py,sha256=f7OA_9zgXEDPoITc8v8SfAR23I4XeFhE3E2_GcAbR6k,1616
|
|
36
|
-
rocket_welder_sdk-1.1.
|
|
37
|
-
rocket_welder_sdk-1.1.
|
|
38
|
-
rocket_welder_sdk-1.1.
|
|
39
|
-
rocket_welder_sdk-1.1.
|
|
35
|
+
rocket_welder_sdk-1.1.34rc1.dist-info/METADATA,sha256=JGM_TMQnCAX1MA9fN-pCS6PeSUTeAN5jgL4-nSJPOSg,24850
|
|
36
|
+
rocket_welder_sdk-1.1.34rc1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
37
|
+
rocket_welder_sdk-1.1.34rc1.dist-info/top_level.txt,sha256=2iZvBjnwVCUW-uDE23-eJld5PZ9-mlPI69QiXM5IrTA,18
|
|
38
|
+
rocket_welder_sdk-1.1.34rc1.dist-info/RECORD,,
|