phystack-hub-client 0.2.1__tar.gz → 0.2.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.
- {phystack_hub_client-0.2.1 → phystack_hub_client-0.2.3}/PKG-INFO +1 -1
- {phystack_hub_client-0.2.1 → phystack_hub_client-0.2.3}/pyproject.toml +1 -1
- {phystack_hub_client-0.2.1 → phystack_hub_client-0.2.3}/src/phystack/hub_client/__init__.py +22 -3
- {phystack_hub_client-0.2.1 → phystack_hub_client-0.2.3}/src/phystack/hub_client/client.py +172 -74
- {phystack_hub_client-0.2.1 → phystack_hub_client-0.2.3}/src/phystack/hub_client/instances/base_instance.py +16 -8
- {phystack_hub_client-0.2.1 → phystack_hub_client-0.2.3}/src/phystack/hub_client/instances/edge_instance.py +7 -3
- {phystack_hub_client-0.2.1 → phystack_hub_client-0.2.3}/src/phystack/hub_client/instances/peripheral_instance.py +5 -1
- {phystack_hub_client-0.2.1 → phystack_hub_client-0.2.3}/src/phystack/hub_client/services/phyhub_connection.py +127 -60
- phystack_hub_client-0.2.3/src/phystack/hub_client/services/signals.py +690 -0
- {phystack_hub_client-0.2.1 → phystack_hub_client-0.2.3}/src/phystack/hub_client/services/webrtc/data_channel.py +50 -7
- {phystack_hub_client-0.2.1 → phystack_hub_client-0.2.3}/src/phystack/hub_client/services/webrtc/media_stream.py +50 -7
- {phystack_hub_client-0.2.1 → phystack_hub_client-0.2.3}/src/phystack/hub_client/twin_registry.py +4 -1
- {phystack_hub_client-0.2.1 → phystack_hub_client-0.2.3}/.gitignore +0 -0
- {phystack_hub_client-0.2.1 → phystack_hub_client-0.2.3}/README.md +0 -0
- {phystack_hub_client-0.2.1 → phystack_hub_client-0.2.3}/examples/browser_test_backend.py +0 -0
- {phystack_hub_client-0.2.1 → phystack_hub_client-0.2.3}/scripts/python-node-test.sh +0 -0
- {phystack_hub_client-0.2.1 → phystack_hub_client-0.2.3}/scripts/webrtc-test.sh +0 -0
- {phystack_hub_client-0.2.1 → phystack_hub_client-0.2.3}/src/phystack/hub_client/instances/__init__.py +0 -0
- {phystack_hub_client-0.2.1 → phystack_hub_client-0.2.3}/src/phystack/hub_client/services/__init__.py +0 -0
- {phystack_hub_client-0.2.1 → phystack_hub_client-0.2.3}/src/phystack/hub_client/services/webrtc/__init__.py +0 -0
- {phystack_hub_client-0.2.1 → phystack_hub_client-0.2.3}/src/phystack/hub_client/twin_messaging.py +0 -0
- {phystack_hub_client-0.2.1 → phystack_hub_client-0.2.3}/src/phystack/hub_client/types/__init__.py +0 -0
- {phystack_hub_client-0.2.1 → phystack_hub_client-0.2.3}/src/phystack/hub_client/types/twin_types.py +0 -0
- {phystack_hub_client-0.2.1 → phystack_hub_client-0.2.3}/tests/test_communication.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: phystack-hub-client
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: Python client for PhyHub - events, actions, DataChannel, and MediaStream
|
|
5
5
|
Project-URL: Homepage, https://github.com/phystack/phystack-pypi
|
|
6
6
|
Project-URL: Documentation, https://docs.phystack.com
|
|
@@ -7,7 +7,7 @@ A Python client for PhyHub that provides:
|
|
|
7
7
|
- WebRTC MediaStream for P2P video/audio
|
|
8
8
|
- Twin instance management (Edge, Peripheral, etc.)
|
|
9
9
|
- Properties API (reported/desired)
|
|
10
|
-
- Settings API
|
|
10
|
+
- Settings API
|
|
11
11
|
|
|
12
12
|
Usage:
|
|
13
13
|
from phystack.hub_client import PhyHubClient
|
|
@@ -27,8 +27,8 @@ Usage:
|
|
|
27
27
|
instance.on_update_desired(lambda props: print("Desired changed:", props))
|
|
28
28
|
|
|
29
29
|
# Settings (for edge apps)
|
|
30
|
-
settings = client.get_settings()
|
|
31
|
-
|
|
30
|
+
settings = await client.get_settings()
|
|
31
|
+
instance.on_update_desired(lambda props: print("Desired changed:", props))
|
|
32
32
|
|
|
33
33
|
# DataChannel
|
|
34
34
|
dc = await instance.get_data_channel(peer_twin_id)
|
|
@@ -63,6 +63,16 @@ from phystack.hub_client.services.webrtc.media_stream import (
|
|
|
63
63
|
PhygridMediaStream,
|
|
64
64
|
WebcamVideoTrack,
|
|
65
65
|
)
|
|
66
|
+
from phystack.hub_client.services.signals import (
|
|
67
|
+
SignalsService,
|
|
68
|
+
InitSignalPayload,
|
|
69
|
+
DataRequestTypeEnum,
|
|
70
|
+
DataResidencyEnum,
|
|
71
|
+
EventTypeEnum,
|
|
72
|
+
CheckoutProps,
|
|
73
|
+
CheckoutProduct,
|
|
74
|
+
PurchaseProps,
|
|
75
|
+
)
|
|
66
76
|
|
|
67
77
|
__version__ = "0.1.0"
|
|
68
78
|
__all__ = [
|
|
@@ -87,4 +97,13 @@ __all__ = [
|
|
|
87
97
|
"MediaStreamOptions",
|
|
88
98
|
"PhygridMediaStream",
|
|
89
99
|
"WebcamVideoTrack",
|
|
100
|
+
# Signals
|
|
101
|
+
"SignalsService",
|
|
102
|
+
"InitSignalPayload",
|
|
103
|
+
"DataRequestTypeEnum",
|
|
104
|
+
"DataResidencyEnum",
|
|
105
|
+
"EventTypeEnum",
|
|
106
|
+
"CheckoutProps",
|
|
107
|
+
"CheckoutProduct",
|
|
108
|
+
"PurchaseProps",
|
|
90
109
|
]
|
|
@@ -10,8 +10,8 @@ from typing import Any, Callable, Optional, Set
|
|
|
10
10
|
|
|
11
11
|
from phystack.hub_client.services.phyhub_connection import (
|
|
12
12
|
PhyHubConnection,
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
ConnectionConfig,
|
|
14
|
+
ConnectionMode,
|
|
15
15
|
)
|
|
16
16
|
from phystack.hub_client.twin_messaging import (
|
|
17
17
|
TwinMessaging,
|
|
@@ -23,6 +23,7 @@ from phystack.hub_client.types.twin_types import (
|
|
|
23
23
|
TwinMessageResultStatus,
|
|
24
24
|
TwinResponse,
|
|
25
25
|
TwinProperties,
|
|
26
|
+
TwinTypeEnum,
|
|
26
27
|
EventPayload,
|
|
27
28
|
)
|
|
28
29
|
from phystack.hub_client.services.webrtc.data_channel import (
|
|
@@ -65,7 +66,12 @@ class PhyHubClient:
|
|
|
65
66
|
TWIN_SUBSCRIBE = "twinSubscribe"
|
|
66
67
|
TWIN_UPDATED = "twinUpdated"
|
|
67
68
|
GET_TWIN_BY_ID = "getTwinById"
|
|
68
|
-
|
|
69
|
+
REPORT_SCREEN_PROPERTIES = "reportScreenTwinProperties"
|
|
70
|
+
REPORT_EDGE_PROPERTIES = "reportEdgeTwinProperties"
|
|
71
|
+
REPORT_PERIPHERAL_PROPERTIES = "reportPeripheralTwinProperties"
|
|
72
|
+
GET_DEVICE_STATUS = "getDeviceStatus"
|
|
73
|
+
GET_DEVICE_INSTANCE = "getDeviceInstance"
|
|
74
|
+
GET_DEVICE_NETWORKS = "getDeviceNetworks"
|
|
69
75
|
|
|
70
76
|
def __init__(
|
|
71
77
|
self,
|
|
@@ -88,17 +94,17 @@ class PhyHubClient:
|
|
|
88
94
|
self._subscribed_twins: Set[str] = set()
|
|
89
95
|
self._twin_message_listeners: dict[str, Set[Callable[[dict[str, Any]], None]]] = {}
|
|
90
96
|
self._twin_update_listeners: dict[str, Set[Callable[[dict[str, Any]], None]]] = {}
|
|
91
|
-
self._settings_update_listeners: Set[Callable[[dict[str, Any]], None]] = set()
|
|
92
97
|
self._twin_data_cache: dict[str, dict[str, Any]] = {}
|
|
93
98
|
self._connected = False
|
|
94
99
|
self._registry: Optional[TwinRegistry] = None
|
|
95
100
|
|
|
96
101
|
if device_id and access_key:
|
|
97
102
|
self._connection = PhyHubConnection(
|
|
98
|
-
|
|
103
|
+
ConnectionConfig(
|
|
104
|
+
mode=ConnectionMode.DIRECT,
|
|
105
|
+
url=phyhub_url or "https://phyhub.eu.omborigrid.net",
|
|
99
106
|
device_id=device_id,
|
|
100
107
|
access_key=access_key,
|
|
101
|
-
phyhub_url=phyhub_url or "https://phyhub.eu.omborigrid.net",
|
|
102
108
|
instance_id=instance_id,
|
|
103
109
|
)
|
|
104
110
|
)
|
|
@@ -147,8 +153,12 @@ class PhyHubClient:
|
|
|
147
153
|
# Set up event handlers
|
|
148
154
|
self._setup_socket_listeners()
|
|
149
155
|
|
|
150
|
-
#
|
|
151
|
-
|
|
156
|
+
# Only direct mode needs explicit authenticate/connectDevice handshake.
|
|
157
|
+
# PhyOS and Simulator handle auth at Socket.IO connection time.
|
|
158
|
+
if self._connection.is_direct:
|
|
159
|
+
await self._initialize_device_twin()
|
|
160
|
+
else:
|
|
161
|
+
print(f"[PhyHubClient] Connected ({self._connection.config.mode.value} mode)")
|
|
152
162
|
|
|
153
163
|
return self
|
|
154
164
|
|
|
@@ -216,18 +226,6 @@ class PhyHubClient:
|
|
|
216
226
|
except Exception as e:
|
|
217
227
|
print(f"[PhyHubClient] Error in twin update listener: {e}")
|
|
218
228
|
|
|
219
|
-
# Check for settings updates on edge instance
|
|
220
|
-
if twin_id == self._instance_id and isinstance(twin_data, dict):
|
|
221
|
-
props = twin_data.get("properties", {})
|
|
222
|
-
desired = props.get("desired", {})
|
|
223
|
-
settings = desired.get("settings", {})
|
|
224
|
-
if settings and self._settings_update_listeners:
|
|
225
|
-
for callback in self._settings_update_listeners:
|
|
226
|
-
try:
|
|
227
|
-
callback(settings)
|
|
228
|
-
except Exception as e:
|
|
229
|
-
print(f"[PhyHubClient] Error in settings update listener: {e}")
|
|
230
|
-
|
|
231
229
|
self._connection.on(self.EVENTS.TWIN_UPDATED, on_twin_updated)
|
|
232
230
|
|
|
233
231
|
async def _initialize_device_twin(self) -> None:
|
|
@@ -322,22 +320,34 @@ class PhyHubClient:
|
|
|
322
320
|
# Fire and forget - use asyncio to schedule
|
|
323
321
|
asyncio.create_task(self._emit_to_socket(self.EVENTS.TWIN_MESSAGE, event_payload))
|
|
324
322
|
|
|
325
|
-
async def _emit_to_socket(
|
|
326
|
-
|
|
323
|
+
async def _emit_to_socket(
|
|
324
|
+
self, method: str, payload: dict[str, Any], callback: bool = False
|
|
325
|
+
) -> Any:
|
|
326
|
+
"""Unified emit — routes through instance ID channel or direct, based on mode.
|
|
327
327
|
|
|
328
328
|
In direct mode: socket.emit(method, payload)
|
|
329
|
-
In PhyOS mode: socket.emit(instanceId, { method, ...payload })
|
|
329
|
+
In PhyOS/Simulator mode: socket.emit(instanceId, { method, ...payload })
|
|
330
|
+
|
|
331
|
+
Args:
|
|
332
|
+
method: Event/method name.
|
|
333
|
+
payload: Data to send.
|
|
334
|
+
callback: If True, wait for ack response (for RPC calls).
|
|
335
|
+
|
|
336
|
+
Returns:
|
|
337
|
+
Response from server if callback is True, else None.
|
|
330
338
|
"""
|
|
331
339
|
if not self._connection:
|
|
332
|
-
return
|
|
340
|
+
return None
|
|
333
341
|
|
|
334
|
-
if
|
|
342
|
+
if self._connection.is_direct:
|
|
335
343
|
# Direct mode: emit to event name directly
|
|
336
|
-
await self._connection.emit(method, payload)
|
|
344
|
+
return await self._connection.emit(method, payload, callback=callback)
|
|
337
345
|
else:
|
|
338
|
-
# PhyOS
|
|
346
|
+
# PhyOS/Simulator: wrap in instance ID channel with method field
|
|
339
347
|
phyos_payload = {"method": method, **payload}
|
|
340
|
-
await self._connection.emit(
|
|
348
|
+
return await self._connection.emit(
|
|
349
|
+
self._instance_id or "", phyos_payload, callback=callback
|
|
350
|
+
)
|
|
341
351
|
|
|
342
352
|
def on_twin_message(
|
|
343
353
|
self,
|
|
@@ -418,10 +428,7 @@ class PhyHubClient:
|
|
|
418
428
|
Returns:
|
|
419
429
|
Twin data dictionary.
|
|
420
430
|
"""
|
|
421
|
-
|
|
422
|
-
return None
|
|
423
|
-
|
|
424
|
-
result = await self._connection.emit(
|
|
431
|
+
result = await self._emit_to_socket(
|
|
425
432
|
self.EVENTS.GET_TWIN_BY_ID,
|
|
426
433
|
{"data": {"twinId": twin_id}},
|
|
427
434
|
callback=True,
|
|
@@ -444,43 +451,7 @@ class PhyHubClient:
|
|
|
444
451
|
return instance.get_settings()
|
|
445
452
|
return {}
|
|
446
453
|
|
|
447
|
-
async def get_edge_settings(self) -> dict[str, Any]:
|
|
448
|
-
"""Alias for get_settings().
|
|
449
454
|
|
|
450
|
-
Returns:
|
|
451
|
-
Settings dictionary.
|
|
452
|
-
"""
|
|
453
|
-
return await self.get_settings()
|
|
454
|
-
|
|
455
|
-
def on_settings_update(
|
|
456
|
-
self, callback: Callable[[dict[str, Any]], None]
|
|
457
|
-
) -> None:
|
|
458
|
-
"""Subscribe to settings changes in edge desired properties.
|
|
459
|
-
|
|
460
|
-
Args:
|
|
461
|
-
callback: Handler called with new settings when they change.
|
|
462
|
-
"""
|
|
463
|
-
self._settings_update_listeners.add(callback)
|
|
464
|
-
|
|
465
|
-
# Subscribe to edge twin updates if connected
|
|
466
|
-
if self._instance_id:
|
|
467
|
-
asyncio.create_task(self.subscribe_twin(self._instance_id))
|
|
468
|
-
|
|
469
|
-
def off_settings_update(
|
|
470
|
-
self, callback: Callable[[dict[str, Any]], None]
|
|
471
|
-
) -> bool:
|
|
472
|
-
"""Remove settings update callback.
|
|
473
|
-
|
|
474
|
-
Args:
|
|
475
|
-
callback: Callback to remove.
|
|
476
|
-
|
|
477
|
-
Returns:
|
|
478
|
-
True if removed, False otherwise.
|
|
479
|
-
"""
|
|
480
|
-
if callback in self._settings_update_listeners:
|
|
481
|
-
self._settings_update_listeners.discard(callback)
|
|
482
|
-
return True
|
|
483
|
-
return False
|
|
484
455
|
|
|
485
456
|
# =========================================================================
|
|
486
457
|
# Twin Update API
|
|
@@ -535,26 +506,153 @@ class PhyHubClient:
|
|
|
535
506
|
# =========================================================================
|
|
536
507
|
|
|
537
508
|
async def update_reported_properties(
|
|
538
|
-
self,
|
|
509
|
+
self,
|
|
510
|
+
twin_id: str,
|
|
511
|
+
properties: dict[str, Any],
|
|
512
|
+
twin_type: Optional[TwinTypeEnum] = None,
|
|
539
513
|
) -> Optional[dict[str, Any]]:
|
|
540
514
|
"""Update reported properties for a twin.
|
|
541
515
|
|
|
542
516
|
Args:
|
|
543
517
|
twin_id: Twin ID to update.
|
|
544
518
|
properties: Properties to set.
|
|
519
|
+
twin_type: Twin type to determine correct event. Defaults to Peripheral.
|
|
545
520
|
|
|
546
521
|
Returns:
|
|
547
522
|
Updated twin data.
|
|
548
523
|
"""
|
|
549
|
-
|
|
550
|
-
|
|
524
|
+
# Dispatch to correct event based on twin type (matches Node.js behavior)
|
|
525
|
+
if twin_type == TwinTypeEnum.Screen:
|
|
526
|
+
event = self.EVENTS.REPORT_SCREEN_PROPERTIES
|
|
527
|
+
elif twin_type == TwinTypeEnum.Edge:
|
|
528
|
+
event = self.EVENTS.REPORT_EDGE_PROPERTIES
|
|
529
|
+
else:
|
|
530
|
+
event = self.EVENTS.REPORT_PERIPHERAL_PROPERTIES
|
|
551
531
|
|
|
552
532
|
payload = {"twinId": twin_id, "data": properties}
|
|
553
|
-
result = await self.
|
|
554
|
-
self.EVENTS.REPORT_PROPERTIES, payload, callback=True
|
|
555
|
-
)
|
|
533
|
+
result = await self._emit_to_socket(event, payload, callback=True)
|
|
556
534
|
return result.get("twin") if result else None
|
|
557
535
|
|
|
536
|
+
# =========================================================================
|
|
537
|
+
# Signals / Analytics API
|
|
538
|
+
# =========================================================================
|
|
539
|
+
|
|
540
|
+
async def initialize_signals(
|
|
541
|
+
self, params: Optional["InitSignalPayload"] = None
|
|
542
|
+
) -> "SignalsService":
|
|
543
|
+
"""Initialize the signals/analytics service.
|
|
544
|
+
|
|
545
|
+
When called without params, auto-populates from device status and
|
|
546
|
+
instance twin data (matches Node.js hub-client behavior).
|
|
547
|
+
|
|
548
|
+
Args:
|
|
549
|
+
params: Optional signal initialization parameters. If None,
|
|
550
|
+
auto-populates from device status and edge instance.
|
|
551
|
+
|
|
552
|
+
Returns:
|
|
553
|
+
Initialized SignalsService instance.
|
|
554
|
+
"""
|
|
555
|
+
from phystack.hub_client.services.signals import SignalsService, InitSignalPayload
|
|
556
|
+
|
|
557
|
+
# Auto-populate from device status + instance (matches Node.js)
|
|
558
|
+
device_status: dict[str, Any] = {}
|
|
559
|
+
instance_data: dict[str, Any] = {}
|
|
560
|
+
|
|
561
|
+
if not params:
|
|
562
|
+
device_status = await self.get_device_status() or {}
|
|
563
|
+
edge_instance = await self.get_instance()
|
|
564
|
+
if edge_instance:
|
|
565
|
+
instance_data = edge_instance._twin_data or {}
|
|
566
|
+
|
|
567
|
+
p = params or InitSignalPayload()
|
|
568
|
+
|
|
569
|
+
payload = InitSignalPayload(
|
|
570
|
+
tenant_id=p.tenant_id or device_status.get("tenantId", ""),
|
|
571
|
+
space_id=p.space_id or device_status.get("spaceId", ""),
|
|
572
|
+
device_id=p.device_id or instance_data.get("deviceId") or device_status.get("deviceId", ""),
|
|
573
|
+
installation_id=p.installation_id or (
|
|
574
|
+
instance_data.get("properties", {}).get("desired", {}).get("installationId", "")
|
|
575
|
+
),
|
|
576
|
+
environment=p.environment or device_status.get("gridEnv", ""),
|
|
577
|
+
data_residency=p.data_residency or (
|
|
578
|
+
device_status.get("dataResidency", "")
|
|
579
|
+
).upper(),
|
|
580
|
+
country=p.country or "SE",
|
|
581
|
+
app_id=p.app_id or "XXXXXXXXXXXXXXXXXXXXXXXX",
|
|
582
|
+
app_version=p.app_version or "XXXXXXXXXXXXXXXXXXXXXXXX",
|
|
583
|
+
installation_version=p.installation_version or "XXXXXXXXXXXXXXXXXXXXXXXX",
|
|
584
|
+
ip=p.ip or (
|
|
585
|
+
device_status.get("ip", [{}])[0].get("ipv4", "N/A")
|
|
586
|
+
if isinstance(device_status.get("ip"), list) and device_status.get("ip")
|
|
587
|
+
else "N/A"
|
|
588
|
+
),
|
|
589
|
+
session_id=p.session_id,
|
|
590
|
+
client_id=p.client_id,
|
|
591
|
+
latitude=p.latitude,
|
|
592
|
+
longitude=p.longitude,
|
|
593
|
+
location_accuracy=p.location_accuracy,
|
|
594
|
+
create_new_session_after_last_activity_mins=p.create_new_session_after_last_activity_mins,
|
|
595
|
+
)
|
|
596
|
+
|
|
597
|
+
service = SignalsService(self, payload)
|
|
598
|
+
await service.initialize()
|
|
599
|
+
return service
|
|
600
|
+
|
|
601
|
+
async def send_signal(
|
|
602
|
+
self, data_type: "DataRequestTypeEnum", data: dict[str, Any]
|
|
603
|
+
) -> Any:
|
|
604
|
+
"""Send a signal to the server.
|
|
605
|
+
|
|
606
|
+
Args:
|
|
607
|
+
data_type: Type of signal (EVENT, SESSION, CLIENT, CHECKOUT, PURCHASE).
|
|
608
|
+
data: Signal data (already key-shortened).
|
|
609
|
+
"""
|
|
610
|
+
from phystack.hub_client.services.signals import DataRequestTypeEnum
|
|
611
|
+
|
|
612
|
+
event_map = {
|
|
613
|
+
DataRequestTypeEnum.EVENT: "sendEventSignal",
|
|
614
|
+
DataRequestTypeEnum.CHECKOUT: "sendEventSignal",
|
|
615
|
+
DataRequestTypeEnum.PURCHASE: "sendEventSignal",
|
|
616
|
+
DataRequestTypeEnum.SESSION: "sendSessionSignal",
|
|
617
|
+
DataRequestTypeEnum.CLIENT: "sendClientSignal",
|
|
618
|
+
}
|
|
619
|
+
event = event_map.get(data_type, "sendEventSignal")
|
|
620
|
+
return await self._emit_to_socket(event, {"data": data})
|
|
621
|
+
|
|
622
|
+
# =========================================================================
|
|
623
|
+
# Device API
|
|
624
|
+
# =========================================================================
|
|
625
|
+
|
|
626
|
+
async def get_device_status(self) -> Optional[dict[str, Any]]:
|
|
627
|
+
"""Get device status (IP, serial, env, etc.).
|
|
628
|
+
|
|
629
|
+
Returns:
|
|
630
|
+
Device status dictionary.
|
|
631
|
+
"""
|
|
632
|
+
return await self._emit_to_socket(
|
|
633
|
+
self.EVENTS.GET_DEVICE_STATUS, {}, callback=True
|
|
634
|
+
)
|
|
635
|
+
|
|
636
|
+
async def get_device_instance(self) -> Optional[dict[str, Any]]:
|
|
637
|
+
"""Get device instance data.
|
|
638
|
+
|
|
639
|
+
Returns:
|
|
640
|
+
Device instance dictionary.
|
|
641
|
+
"""
|
|
642
|
+
return await self._emit_to_socket(
|
|
643
|
+
self.EVENTS.GET_DEVICE_INSTANCE, {}, callback=True
|
|
644
|
+
)
|
|
645
|
+
|
|
646
|
+
async def get_device_networks(self) -> Optional[dict[str, Any]]:
|
|
647
|
+
"""Get available networks on the device.
|
|
648
|
+
|
|
649
|
+
Returns:
|
|
650
|
+
Device networks dictionary.
|
|
651
|
+
"""
|
|
652
|
+
return await self._emit_to_socket(
|
|
653
|
+
self.EVENTS.GET_DEVICE_NETWORKS, {}, callback=True
|
|
654
|
+
)
|
|
655
|
+
|
|
558
656
|
# =========================================================================
|
|
559
657
|
# WebRTC Helpers
|
|
560
658
|
# =========================================================================
|
|
@@ -148,20 +148,24 @@ class BaseInstance:
|
|
|
148
148
|
|
|
149
149
|
async def on_data_channel(
|
|
150
150
|
self,
|
|
151
|
-
target_twin_id: str,
|
|
152
151
|
callback: Callable[["PhygridDataChannel"], None],
|
|
153
152
|
channel_name: str = "default",
|
|
154
153
|
) -> None:
|
|
155
|
-
"""Listen for incoming DataChannel from
|
|
154
|
+
"""Listen for incoming DataChannel from any twin.
|
|
155
|
+
|
|
156
|
+
Accepts the first incoming connection and locks to that source
|
|
157
|
+
(matches Node.js hub-client behavior).
|
|
156
158
|
|
|
157
159
|
Args:
|
|
158
|
-
target_twin_id: ID of the twin to listen from.
|
|
159
160
|
callback: Handler for incoming channel.
|
|
160
161
|
channel_name: Name of the channel to listen for.
|
|
161
162
|
"""
|
|
163
|
+
from phystack.hub_client.services.webrtc.data_channel import DataChannelOptions
|
|
164
|
+
|
|
162
165
|
channel = await self._client.create_data_channel(
|
|
163
|
-
target_twin_id=
|
|
166
|
+
target_twin_id="",
|
|
164
167
|
is_initiator=False,
|
|
168
|
+
options=DataChannelOptions(accept_from_any_source=True),
|
|
165
169
|
channel_name=channel_name,
|
|
166
170
|
blocking=False,
|
|
167
171
|
)
|
|
@@ -201,20 +205,24 @@ class BaseInstance:
|
|
|
201
205
|
|
|
202
206
|
async def on_media_stream(
|
|
203
207
|
self,
|
|
204
|
-
target_twin_id: str,
|
|
205
208
|
callback: Callable[["PhygridMediaStream"], None],
|
|
206
209
|
stream_name: str = "default",
|
|
207
210
|
) -> None:
|
|
208
|
-
"""Listen for incoming MediaStream from
|
|
211
|
+
"""Listen for incoming MediaStream from any twin.
|
|
212
|
+
|
|
213
|
+
Accepts the first incoming connection and locks to that source
|
|
214
|
+
(matches Node.js hub-client behavior).
|
|
209
215
|
|
|
210
216
|
Args:
|
|
211
|
-
target_twin_id: ID of the twin to listen from.
|
|
212
217
|
callback: Handler for incoming stream.
|
|
213
218
|
stream_name: Name of the stream to listen for.
|
|
214
219
|
"""
|
|
220
|
+
from phystack.hub_client.services.webrtc.media_stream import MediaStreamOptions
|
|
221
|
+
|
|
215
222
|
stream = await self._client.create_media_stream(
|
|
216
|
-
target_twin_id=
|
|
223
|
+
target_twin_id="",
|
|
217
224
|
is_initiator=False,
|
|
225
|
+
options=MediaStreamOptions(accept_from_any_source=True),
|
|
218
226
|
stream_name=stream_name,
|
|
219
227
|
blocking=False,
|
|
220
228
|
)
|
|
@@ -55,7 +55,11 @@ class EdgeInstance(BaseInstance):
|
|
|
55
55
|
Returns:
|
|
56
56
|
Updated twin data.
|
|
57
57
|
"""
|
|
58
|
-
|
|
58
|
+
from phystack.hub_client.types.twin_types import TwinTypeEnum
|
|
59
|
+
|
|
60
|
+
result = await self._client.update_reported_properties(
|
|
61
|
+
self.id, properties, twin_type=TwinTypeEnum.Edge
|
|
62
|
+
)
|
|
59
63
|
if result:
|
|
60
64
|
self._update_twin_data(result)
|
|
61
65
|
return result or {}
|
|
@@ -182,7 +186,7 @@ class EdgeInstance(BaseInstance):
|
|
|
182
186
|
}
|
|
183
187
|
}
|
|
184
188
|
|
|
185
|
-
result = await self._client.
|
|
189
|
+
result = await self._client._emit_to_socket(
|
|
186
190
|
"createPeripheralTwin", payload, callback=True
|
|
187
191
|
)
|
|
188
192
|
return result.get("twin", {}) if result else {}
|
|
@@ -194,7 +198,7 @@ class EdgeInstance(BaseInstance):
|
|
|
194
198
|
List of peripheral twin data.
|
|
195
199
|
"""
|
|
196
200
|
payload = {"data": {"instanceId": self.id}}
|
|
197
|
-
result = await self._client.
|
|
201
|
+
result = await self._client._emit_to_socket(
|
|
198
202
|
"getPeripheralTwins", payload, callback=True
|
|
199
203
|
)
|
|
200
204
|
return result.get("twins", []) if result else []
|
|
@@ -57,7 +57,11 @@ class PeripheralInstance(BaseInstance):
|
|
|
57
57
|
Returns:
|
|
58
58
|
Updated twin data.
|
|
59
59
|
"""
|
|
60
|
-
|
|
60
|
+
from phystack.hub_client.types.twin_types import TwinTypeEnum
|
|
61
|
+
|
|
62
|
+
result = await self._client.update_reported_properties(
|
|
63
|
+
self.id, properties, twin_type=TwinTypeEnum.Peripheral
|
|
64
|
+
)
|
|
61
65
|
if result:
|
|
62
66
|
self._update_twin_data(result)
|
|
63
67
|
return result or {}
|