rocket-welder-sdk 1.1.34a2__py3-none-any.whl → 1.1.34.dev8__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.
@@ -16,11 +16,22 @@ from .opencv_controller import OpenCvController
16
16
  from .periodic_timer import PeriodicTimer, PeriodicTimerSync
17
17
  from .rocket_welder_client import RocketWelderClient
18
18
  from .session_id import (
19
+ # Explicit URL functions (PREFERRED - set by rocket-welder2)
20
+ ACTIONS_SINK_URL_ENV,
21
+ KEYPOINTS_SINK_URL_ENV,
22
+ SEGMENTATION_SINK_URL_ENV,
23
+ # SessionId-derived URL functions (fallback for backwards compatibility)
19
24
  get_actions_url,
25
+ get_actions_url_from_env,
26
+ get_configured_nng_urls,
20
27
  get_keypoints_url,
28
+ get_keypoints_url_from_env,
21
29
  get_nng_urls,
30
+ get_nng_urls_from_env,
22
31
  get_segmentation_url,
32
+ get_segmentation_url_from_env,
23
33
  get_session_id_from_env,
34
+ has_explicit_nng_urls,
24
35
  parse_session_id,
25
36
  )
26
37
 
@@ -49,7 +60,10 @@ if _log_level:
49
60
  pass # Invalid log level, ignore
50
61
 
51
62
  __all__ = [
63
+ "ACTIONS_SINK_URL_ENV",
52
64
  "FRAME_METADATA_SIZE",
65
+ "KEYPOINTS_SINK_URL_ENV",
66
+ "SEGMENTATION_SINK_URL_ENV",
53
67
  "BytesSize",
54
68
  "Client",
55
69
  "ConnectionMode",
@@ -66,11 +80,16 @@ __all__ = [
66
80
  "PeriodicTimerSync",
67
81
  "Protocol",
68
82
  "RocketWelderClient",
69
- # SessionId utilities for NNG URL generation
70
83
  "get_actions_url",
84
+ "get_actions_url_from_env",
85
+ "get_configured_nng_urls",
71
86
  "get_keypoints_url",
87
+ "get_keypoints_url_from_env",
72
88
  "get_nng_urls",
89
+ "get_nng_urls_from_env",
73
90
  "get_segmentation_url",
91
+ "get_segmentation_url_from_env",
74
92
  "get_session_id_from_env",
93
+ "has_explicit_nng_urls",
75
94
  "parse_session_id",
76
95
  ]
@@ -438,7 +438,9 @@ class OneWayShmController(IController):
438
438
  sqrt_pixels = math.sqrt(pixels)
439
439
  if sqrt_pixels == int(sqrt_pixels):
440
440
  dimension = int(sqrt_pixels)
441
- logger.info(f"Pixel data size {pixel_data_size} suggests {dimension}x{dimension} RGB")
441
+ logger.info(
442
+ f"Pixel data size {pixel_data_size} suggests {dimension}x{dimension} RGB"
443
+ )
442
444
  pixel_data = np.frombuffer(frame.data[FRAME_METADATA_SIZE:], dtype=np.uint8)
443
445
  return pixel_data.reshape((dimension, dimension, 3)) # type: ignore[no-any-return]
444
446
 
@@ -448,7 +450,9 @@ class OneWayShmController(IController):
448
450
  sqrt_pixels = math.sqrt(pixels)
449
451
  if sqrt_pixels == int(sqrt_pixels):
450
452
  dimension = int(sqrt_pixels)
451
- logger.info(f"Pixel data size {pixel_data_size} suggests {dimension}x{dimension} RGBA")
453
+ logger.info(
454
+ f"Pixel data size {pixel_data_size} suggests {dimension}x{dimension} RGBA"
455
+ )
452
456
  pixel_data = np.frombuffer(frame.data[FRAME_METADATA_SIZE:], dtype=np.uint8)
453
457
  return pixel_data.reshape((dimension, dimension, 4)) # type: ignore[no-any-return]
454
458
 
@@ -16,7 +16,11 @@ 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 get_nng_urls, get_session_id_from_env
19
+ from .session_id import (
20
+ get_configured_nng_urls,
21
+ get_nng_urls_from_env,
22
+ has_explicit_nng_urls,
23
+ )
20
24
  from .transport.nng_transport import NngFrameSink
21
25
 
22
26
  if TYPE_CHECKING:
@@ -90,27 +94,33 @@ class RocketWelderClient:
90
94
  """
91
95
  return self._nng_publishers
92
96
 
93
- def _create_nng_publishers(self, session_id: str) -> None:
97
+ def _create_nng_publishers(self) -> None:
94
98
  """Create NNG publishers for result streaming.
95
99
 
96
- Args:
97
- session_id: SessionId string (e.g., "ps-{guid}")
100
+ URLs are read from environment variables (preferred) or derived from SessionId (fallback).
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)
98
105
  """
99
106
  try:
100
- urls = get_nng_urls(session_id)
107
+ urls = get_configured_nng_urls()
101
108
 
102
109
  for name, url in urls.items():
103
110
  sink = NngFrameSink.create_publisher(url)
104
111
  self._nng_publishers[name] = sink
105
112
  logger.info("NNG publisher ready: %s at %s", name, url)
106
113
 
114
+ # Log configuration summary
107
115
  logger.info(
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"],
116
+ "NNG publishers configured: seg=%s, kp=%s, actions=%s",
117
+ urls.get("segmentation", "(not configured)"),
118
+ urls.get("keypoints", "(not configured)"),
119
+ urls.get("actions", "(not configured)"),
113
120
  )
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)
114
124
  except Exception as ex:
115
125
  logger.warning("Failed to create NNG publishers: %s", ex)
116
126
  # Don't fail start() - NNG is optional for backwards compatibility
@@ -162,10 +172,20 @@ class RocketWelderClient:
162
172
  else:
163
173
  raise ValueError(f"Unsupported protocol: {self._connection.protocol}")
164
174
 
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)
175
+ # Auto-create NNG publishers if URLs are configured
176
+ # (explicit URLs via SEGMENTATION_SINK_URL etc., or derived from SessionId)
177
+ if has_explicit_nng_urls():
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
+ )
169
189
 
170
190
  # If preview is enabled, wrap the callback to capture frames
171
191
  if self._preview_enabled:
@@ -7,6 +7,22 @@ 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).
10
26
  """
11
27
 
12
28
  from __future__ import annotations
@@ -20,6 +36,11 @@ logger = logging.getLogger(__name__)
20
36
  SESSION_ID_PREFIX = "ps-"
21
37
  SESSION_ID_ENV_VAR = "SessionId"
22
38
 
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
+
23
44
 
24
45
  def parse_session_id(session_id: str) -> uuid.UUID:
25
46
  """Parse SessionId (ps-{guid}) to extract Guid.
@@ -113,3 +134,105 @@ def get_actions_url(session_id: str) -> str:
113
134
  """
114
135
  guid = parse_session_id(session_id)
115
136
  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,11 +28,3 @@ __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.34a2
3
+ Version: 1.1.34.dev8
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,16 +1,16 @@
1
- rocket_welder_sdk/__init__.py,sha256=7jawqof-tt0S0G7CMMOmHRsVLbUf-o8sSREP1VxEeJ4,2400
1
+ rocket_welder_sdk/__init__.py,sha256=pcYOCqqYuK8oJwkFRnWej4uNfEkuYWXP6jcUhPSLgrc,3041
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=X7D7OyiuHhGTrmrSNG2Tljsy1_4PGRObytB4dLyvRrg,32600
4
+ rocket_welder_sdk/controllers.py,sha256=WY3fgUUrlicA_ibDhvsfsF0ucD7RuoHuL-BWojAhjtQ,32692
5
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=2tGL98hLXU_Xl2LzjhdLpQkp9oxzb4D3WmPOcMZMyw4,17474
11
+ rocket_welder_sdk/rocket_welder_client.py,sha256=0SNsrP9SePTHNLbfKyt-71UYs2owrZwesiwOXNglI4c,18515
12
12
  rocket_welder_sdk/segmentation_result.py,sha256=q3n8m1sooPcattfXisL9em5gZKbEZ1ueGqeXfOrdaHY,13417
13
- rocket_welder_sdk/session_id.py,sha256=4RVNxuMzJsJ3Me1LveTe_RSDevEUsOozlamSRMXfXGA,3114
13
+ rocket_welder_sdk/session_id.py,sha256=sRhzQw90shqq_DJVtrsSggcGZ775kz7cRfbI-1LMeSA,7027
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
@@ -19,7 +19,7 @@ rocket_welder_sdk/high_level/connection_strings.py,sha256=4undnkbWZ837vY-o6ybIj1
19
19
  rocket_welder_sdk/high_level/data_context.py,sha256=Pmwsl9MgBfKA9BqmBJmAVRvnaqPdjnq2rZEA_pzzYsw,4585
20
20
  rocket_welder_sdk/high_level/schema.py,sha256=UlefNAV2UL9eO_Th2q19a7tf_eoaeLE92fYZ5LNq7-M,4849
21
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
22
+ rocket_welder_sdk/transport/__init__.py,sha256=DYmZpohGPU7RhS6EdVT_BwCy5MZzyTQ6Eymm8TpmxJ8,751
23
23
  rocket_welder_sdk/transport/frame_sink.py,sha256=16dUefZF1QJv62Ig0ezPR6nEho_7A3WJu4M9_PPMqJM,2164
24
24
  rocket_welder_sdk/transport/frame_source.py,sha256=G1rBAQS1AgOOdtASB0_CYon8g20hUGXpP2exCp5hlhk,2169
25
25
  rocket_welder_sdk/transport/nng_transport.py,sha256=o-qgcmHCGnwtdPe-mwwrC-a9H0rgS-VdH2QvU-6kFlI,5838
@@ -32,7 +32,7 @@ rocket_welder_sdk/ui/icons.py,sha256=DcDklZkPmiEzlOD4IR7VTJOtGPCuuh_OM_WN7ScghWE
32
32
  rocket_welder_sdk/ui/ui_events_projection.py,sha256=siiNhjLEBOPfTKw1ZhOPGkwIN5rLDH7V9VCZTNrhEtQ,7836
33
33
  rocket_welder_sdk/ui/ui_service.py,sha256=uRdpyJGoCQmtOli_HKSrxLwhZYG-XRuHIYdkmFz1zNk,12026
34
34
  rocket_welder_sdk/ui/value_types.py,sha256=f7OA_9zgXEDPoITc8v8SfAR23I4XeFhE3E2_GcAbR6k,1616
35
- rocket_welder_sdk-1.1.34a2.dist-info/METADATA,sha256=XlxEOkkIEDYqUlxlPbBv3ZhWNeiqo9cXjnHm8yY_16A,24849
36
- rocket_welder_sdk-1.1.34a2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
37
- rocket_welder_sdk-1.1.34a2.dist-info/top_level.txt,sha256=2iZvBjnwVCUW-uDE23-eJld5PZ9-mlPI69QiXM5IrTA,18
38
- rocket_welder_sdk-1.1.34a2.dist-info/RECORD,,
35
+ rocket_welder_sdk-1.1.34.dev8.dist-info/METADATA,sha256=a6DSnVRI49bvfQMw80JqbChtXjnMR7p7eBDSD_bdivU,24852
36
+ rocket_welder_sdk-1.1.34.dev8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
37
+ rocket_welder_sdk-1.1.34.dev8.dist-info/top_level.txt,sha256=2iZvBjnwVCUW-uDE23-eJld5PZ9-mlPI69QiXM5IrTA,18
38
+ rocket_welder_sdk-1.1.34.dev8.dist-info/RECORD,,