piphi-runtime-kit-python 0.4.1__py3-none-any.whl → 0.4.2__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.
- piphi_runtime_kit_python/__init__.py +8 -0
- piphi_runtime_kit_python/runtime/dispatch.py +50 -17
- piphi_runtime_kit_python/runtime/identity.py +80 -0
- piphi_runtime_kit_python/runtime/registry.py +17 -5
- piphi_runtime_kit_python/schemas.py +66 -1
- {piphi_runtime_kit_python-0.4.1.dist-info → piphi_runtime_kit_python-0.4.2.dist-info}/METADATA +4 -4
- {piphi_runtime_kit_python-0.4.1.dist-info → piphi_runtime_kit_python-0.4.2.dist-info}/RECORD +10 -9
- {piphi_runtime_kit_python-0.4.1.dist-info → piphi_runtime_kit_python-0.4.2.dist-info}/WHEEL +0 -0
- {piphi_runtime_kit_python-0.4.1.dist-info → piphi_runtime_kit_python-0.4.2.dist-info}/entry_points.txt +0 -0
- {piphi_runtime_kit_python-0.4.1.dist-info → piphi_runtime_kit_python-0.4.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -49,6 +49,7 @@ from .runtime.events import (
|
|
|
49
49
|
normalize_event_payload,
|
|
50
50
|
)
|
|
51
51
|
from .runtime.health import build_runtime_diagnostics_response, build_runtime_health_response
|
|
52
|
+
from .runtime.identity import build_runtime_identity, resolve_config_id, resolve_device_id
|
|
52
53
|
from .runtime.lifespan import (
|
|
53
54
|
DEFAULT_CORE_CLIENT_TIMEOUT_SECONDS,
|
|
54
55
|
DEFAULT_RUNTIME_CONTAINER_ID_ENV_NAME,
|
|
@@ -80,6 +81,8 @@ from .schemas import (
|
|
|
80
81
|
IntegrationCommandRequest,
|
|
81
82
|
IntegrationDiscoveryRequest,
|
|
82
83
|
IntegrationDiscoveryResponse,
|
|
84
|
+
RuntimeEntityCommandFieldResponse,
|
|
85
|
+
RuntimeEntityCommandResponse,
|
|
83
86
|
RuntimeEntityDashboardResponse,
|
|
84
87
|
RuntimeEntitiesResponse,
|
|
85
88
|
RuntimeEntityResponse,
|
|
@@ -113,6 +116,8 @@ __all__ = [
|
|
|
113
116
|
"IntegrationCommandRequest",
|
|
114
117
|
"IntegrationDiscoveryRequest",
|
|
115
118
|
"IntegrationDiscoveryResponse",
|
|
119
|
+
"RuntimeEntityCommandFieldResponse",
|
|
120
|
+
"RuntimeEntityCommandResponse",
|
|
116
121
|
"RuntimeEntityDashboardResponse",
|
|
117
122
|
"RuntimeEntitiesResponse",
|
|
118
123
|
"RuntimeEntityResponse",
|
|
@@ -144,6 +149,7 @@ __all__ = [
|
|
|
144
149
|
"build_event_ingest_response",
|
|
145
150
|
"build_event_list_response",
|
|
146
151
|
"build_local_event_record",
|
|
152
|
+
"build_runtime_identity",
|
|
147
153
|
"build_core_auth_headers",
|
|
148
154
|
"build_config_apply_response",
|
|
149
155
|
"build_config_remove_response",
|
|
@@ -175,6 +181,8 @@ __all__ = [
|
|
|
175
181
|
"schedule_telemetry_delivery",
|
|
176
182
|
"shutdown_background_tasks",
|
|
177
183
|
"track_background_task",
|
|
184
|
+
"resolve_config_id",
|
|
185
|
+
"resolve_device_id",
|
|
178
186
|
"validate_typed_config",
|
|
179
187
|
"validate_typed_configs",
|
|
180
188
|
"DEFAULT_SOURCE_TOPIC_PREFIX",
|
|
@@ -2,8 +2,10 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
"""Helpers for background dispatch of telemetry and event delivery."""
|
|
4
4
|
|
|
5
|
+
import asyncio
|
|
5
6
|
from typing import Any, Callable, Mapping
|
|
6
7
|
|
|
8
|
+
from .errors import CoreDeliveryError
|
|
7
9
|
from .events import EventClient
|
|
8
10
|
from .tasks import create_tracked_task
|
|
9
11
|
from .telemetry import TelemetryClient
|
|
@@ -14,6 +16,9 @@ EventRecorder = Callable[[dict[str, Any]], Any]
|
|
|
14
16
|
SkipHandler = Callable[[str, dict[str, Any]], Any]
|
|
15
17
|
ErrorHandler = Callable[[Exception, dict[str, Any]], Any]
|
|
16
18
|
|
|
19
|
+
DEFAULT_RETRYABLE_DELIVERY_ATTEMPTS = 5
|
|
20
|
+
DEFAULT_RETRYABLE_DELIVERY_INITIAL_DELAY_SECONDS = 0.5
|
|
21
|
+
|
|
17
22
|
|
|
18
23
|
def build_local_event_record(
|
|
19
24
|
*,
|
|
@@ -36,6 +41,30 @@ def build_local_event_record(
|
|
|
36
41
|
}
|
|
37
42
|
|
|
38
43
|
|
|
44
|
+
async def _run_with_retryable_core_delivery_backoff(
|
|
45
|
+
delivery: Callable[[], Any],
|
|
46
|
+
*,
|
|
47
|
+
max_attempts: int = DEFAULT_RETRYABLE_DELIVERY_ATTEMPTS,
|
|
48
|
+
initial_delay_seconds: float = DEFAULT_RETRYABLE_DELIVERY_INITIAL_DELAY_SECONDS,
|
|
49
|
+
) -> Any:
|
|
50
|
+
"""Retry transient Core delivery failures with a short exponential backoff."""
|
|
51
|
+
|
|
52
|
+
attempt = 1
|
|
53
|
+
delay_seconds = initial_delay_seconds
|
|
54
|
+
while True:
|
|
55
|
+
try:
|
|
56
|
+
result = delivery()
|
|
57
|
+
if asyncio.iscoroutine(result):
|
|
58
|
+
return await result
|
|
59
|
+
return result
|
|
60
|
+
except CoreDeliveryError as exc:
|
|
61
|
+
if not exc.retryable or attempt >= max_attempts:
|
|
62
|
+
raise
|
|
63
|
+
await asyncio.sleep(delay_seconds)
|
|
64
|
+
attempt += 1
|
|
65
|
+
delay_seconds *= 2
|
|
66
|
+
|
|
67
|
+
|
|
39
68
|
async def dispatch_telemetry_delivery(
|
|
40
69
|
*,
|
|
41
70
|
telemetry_client: TelemetryClient,
|
|
@@ -59,13 +88,15 @@ async def dispatch_telemetry_delivery(
|
|
|
59
88
|
return False
|
|
60
89
|
|
|
61
90
|
try:
|
|
62
|
-
await
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
91
|
+
await _run_with_retryable_core_delivery_backoff(
|
|
92
|
+
lambda: telemetry_client.send_metrics(
|
|
93
|
+
device_id=device_id,
|
|
94
|
+
metrics=metrics,
|
|
95
|
+
auth_context=auth_context,
|
|
96
|
+
container_id=resolved_container_id,
|
|
97
|
+
units=units,
|
|
98
|
+
timestamp=timestamp,
|
|
99
|
+
)
|
|
69
100
|
)
|
|
70
101
|
return True
|
|
71
102
|
except Exception as exc:
|
|
@@ -119,16 +150,18 @@ async def dispatch_event_delivery(
|
|
|
119
150
|
) -> bool:
|
|
120
151
|
"""Send one event to Core and return whether delivery succeeded."""
|
|
121
152
|
try:
|
|
122
|
-
event_sent = await
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
153
|
+
event_sent = await _run_with_retryable_core_delivery_backoff(
|
|
154
|
+
lambda: event_client.send_event(
|
|
155
|
+
event_type=event_type,
|
|
156
|
+
integration_id=device.get("integration_id"),
|
|
157
|
+
config_id=device.get("config_id"),
|
|
158
|
+
auth_context=auth_context,
|
|
159
|
+
container_id=device.get("container_id"),
|
|
160
|
+
device_id=device.get("device_id"),
|
|
161
|
+
payload=payload,
|
|
162
|
+
source=source,
|
|
163
|
+
severity=severity,
|
|
164
|
+
)
|
|
132
165
|
)
|
|
133
166
|
if not event_sent and on_skipped is not None:
|
|
134
167
|
on_skipped(
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
"""Helpers for keeping runtime config and device identity explicit."""
|
|
4
|
+
|
|
5
|
+
from typing import Any, Mapping
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def _coerce_optional_string(value: Any) -> str | None:
|
|
9
|
+
if value is None:
|
|
10
|
+
return None
|
|
11
|
+
text = str(value).strip()
|
|
12
|
+
return text or None
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _first_present(payload: Mapping[str, Any], *keys: str) -> str | None:
|
|
16
|
+
for key in keys:
|
|
17
|
+
resolved = _coerce_optional_string(payload.get(key))
|
|
18
|
+
if resolved:
|
|
19
|
+
return resolved
|
|
20
|
+
return None
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def resolve_config_id(payload: Mapping[str, Any] | Any) -> str:
|
|
24
|
+
"""Resolve the Core-owned config id from a config-like payload."""
|
|
25
|
+
|
|
26
|
+
if isinstance(payload, Mapping):
|
|
27
|
+
return _first_present(payload, "config_id", "configId", "id") or "missing"
|
|
28
|
+
return (
|
|
29
|
+
_coerce_optional_string(getattr(payload, "config_id", None))
|
|
30
|
+
or _coerce_optional_string(getattr(payload, "configId", None))
|
|
31
|
+
or _coerce_optional_string(getattr(payload, "id", None))
|
|
32
|
+
or "missing"
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def resolve_device_id(payload: Mapping[str, Any] | Any) -> str:
|
|
37
|
+
"""Resolve the integration-owned device id from a config-like payload."""
|
|
38
|
+
|
|
39
|
+
if isinstance(payload, Mapping):
|
|
40
|
+
return _first_present(payload, "device_id", "deviceId", "id") or "missing"
|
|
41
|
+
return (
|
|
42
|
+
_coerce_optional_string(getattr(payload, "device_id", None))
|
|
43
|
+
or _coerce_optional_string(getattr(payload, "deviceId", None))
|
|
44
|
+
or _coerce_optional_string(getattr(payload, "id", None))
|
|
45
|
+
or "missing"
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def build_runtime_identity(
|
|
50
|
+
payload: Mapping[str, Any] | Any,
|
|
51
|
+
*,
|
|
52
|
+
container_id: str | None = None,
|
|
53
|
+
integration_id: str | None = None,
|
|
54
|
+
) -> dict[str, Any]:
|
|
55
|
+
"""Build a canonical runtime identity record for one config-backed device."""
|
|
56
|
+
|
|
57
|
+
resolved = {
|
|
58
|
+
"config_id": resolve_config_id(payload),
|
|
59
|
+
"device_id": resolve_device_id(payload),
|
|
60
|
+
}
|
|
61
|
+
payload_container_id = (
|
|
62
|
+
_first_present(payload, "container_id", "containerId")
|
|
63
|
+
if isinstance(payload, Mapping)
|
|
64
|
+
else (
|
|
65
|
+
_coerce_optional_string(getattr(payload, "container_id", None))
|
|
66
|
+
or _coerce_optional_string(getattr(payload, "containerId", None))
|
|
67
|
+
)
|
|
68
|
+
)
|
|
69
|
+
payload_integration_id = (
|
|
70
|
+
_first_present(payload, "integration_id", "integrationId")
|
|
71
|
+
if isinstance(payload, Mapping)
|
|
72
|
+
else (
|
|
73
|
+
_coerce_optional_string(getattr(payload, "integration_id", None))
|
|
74
|
+
or _coerce_optional_string(getattr(payload, "integrationId", None))
|
|
75
|
+
)
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
resolved["container_id"] = _coerce_optional_string(container_id) or payload_container_id
|
|
79
|
+
resolved["integration_id"] = _coerce_optional_string(integration_id) or payload_integration_id
|
|
80
|
+
return resolved
|
|
@@ -50,18 +50,30 @@ class RuntimeRegistry(Generic[TEntry, TState, TEvent]):
|
|
|
50
50
|
first_entry_id = next(iter(self.entries))
|
|
51
51
|
return self.entries[first_entry_id]
|
|
52
52
|
|
|
53
|
-
def update_state(
|
|
53
|
+
def update_state(
|
|
54
|
+
self,
|
|
55
|
+
entry_id: str,
|
|
56
|
+
state: dict[str, Any],
|
|
57
|
+
*,
|
|
58
|
+
device_id: str | None = None,
|
|
59
|
+
) -> dict[str, Any]:
|
|
54
60
|
"""Store the latest state snapshot and mirror it onto the active entry."""
|
|
55
61
|
timestamp = dt.datetime.now(dt.timezone.utc).isoformat()
|
|
62
|
+
entry = self.entries.get(entry_id)
|
|
63
|
+
resolved_device_id = (
|
|
64
|
+
device_id
|
|
65
|
+
or (str(entry.get("device_id")) if entry and entry.get("device_id") else None)
|
|
66
|
+
or entry_id
|
|
67
|
+
)
|
|
56
68
|
latest_state = {
|
|
57
|
-
"device_id":
|
|
69
|
+
"device_id": resolved_device_id,
|
|
58
70
|
"state": state,
|
|
59
71
|
"last_updated": timestamp,
|
|
60
72
|
}
|
|
61
73
|
self.state_snapshots[entry_id] = latest_state
|
|
62
|
-
if
|
|
63
|
-
|
|
64
|
-
|
|
74
|
+
if entry is not None:
|
|
75
|
+
entry["latest_state"] = state
|
|
76
|
+
entry["last_updated"] = timestamp
|
|
65
77
|
return latest_state
|
|
66
78
|
|
|
67
79
|
def append_event(self, event: TEvent) -> TEvent:
|
|
@@ -11,8 +11,26 @@ from pydantic import AliasChoices, BaseModel, ConfigDict, Field
|
|
|
11
11
|
|
|
12
12
|
class RuntimeConfig(BaseModel):
|
|
13
13
|
"""Base runtime config model with a required config id and extensible fields."""
|
|
14
|
+
|
|
15
|
+
model_config = ConfigDict(populate_by_name=True, extra="allow")
|
|
16
|
+
|
|
14
17
|
id: str
|
|
15
|
-
|
|
18
|
+
config_id: str | None = Field(
|
|
19
|
+
default=None,
|
|
20
|
+
validation_alias=AliasChoices("config_id", "configId"),
|
|
21
|
+
)
|
|
22
|
+
container_id: str | None = Field(
|
|
23
|
+
default=None,
|
|
24
|
+
validation_alias=AliasChoices("container_id", "containerId"),
|
|
25
|
+
)
|
|
26
|
+
integration_id: str | None = Field(
|
|
27
|
+
default=None,
|
|
28
|
+
validation_alias=AliasChoices("integration_id", "integrationId"),
|
|
29
|
+
)
|
|
30
|
+
device_id: str | None = Field(
|
|
31
|
+
default=None,
|
|
32
|
+
validation_alias=AliasChoices("device_id", "deviceId"),
|
|
33
|
+
)
|
|
16
34
|
|
|
17
35
|
|
|
18
36
|
class RuntimeConfigSnapshot(BaseModel):
|
|
@@ -94,6 +112,44 @@ class RuntimeEntityDashboardResponse(BaseModel):
|
|
|
94
112
|
metadata: dict[str, Any] = Field(default_factory=dict)
|
|
95
113
|
|
|
96
114
|
|
|
115
|
+
class RuntimeEntityCommandFieldResponse(BaseModel):
|
|
116
|
+
"""Optional per-command argument metadata returned by a runtime entity."""
|
|
117
|
+
|
|
118
|
+
model_config = ConfigDict(populate_by_name=True, extra="allow")
|
|
119
|
+
|
|
120
|
+
type: str
|
|
121
|
+
label: str | None = None
|
|
122
|
+
description: str | None = None
|
|
123
|
+
required: bool = False
|
|
124
|
+
default: Any | None = None
|
|
125
|
+
minimum: float | None = Field(
|
|
126
|
+
default=None,
|
|
127
|
+
validation_alias=AliasChoices("minimum", "min"),
|
|
128
|
+
)
|
|
129
|
+
maximum: float | None = Field(
|
|
130
|
+
default=None,
|
|
131
|
+
validation_alias=AliasChoices("maximum", "max"),
|
|
132
|
+
)
|
|
133
|
+
step: float | None = None
|
|
134
|
+
unit: str | None = None
|
|
135
|
+
options: list[Any] = Field(default_factory=list)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class RuntimeEntityCommandResponse(BaseModel):
|
|
139
|
+
"""One device-scoped command exposed by a runtime entity."""
|
|
140
|
+
|
|
141
|
+
model_config = ConfigDict(populate_by_name=True, extra="allow")
|
|
142
|
+
|
|
143
|
+
id: str
|
|
144
|
+
label: str | None = None
|
|
145
|
+
description: str | None = None
|
|
146
|
+
kind: str | None = None
|
|
147
|
+
args_schema: dict[str, RuntimeEntityCommandFieldResponse] = Field(
|
|
148
|
+
default_factory=dict,
|
|
149
|
+
validation_alias=AliasChoices("args_schema", "argsSchema"),
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
|
|
97
153
|
class RuntimeEntityResponse(BaseModel):
|
|
98
154
|
"""One live runtime entity tied to a configured device/account."""
|
|
99
155
|
|
|
@@ -122,6 +178,15 @@ class RuntimeEntityResponse(BaseModel):
|
|
|
122
178
|
default=None,
|
|
123
179
|
validation_alias=AliasChoices("entity_type", "entityType"),
|
|
124
180
|
)
|
|
181
|
+
available_commands: list[RuntimeEntityCommandResponse | str] = Field(
|
|
182
|
+
default_factory=list,
|
|
183
|
+
validation_alias=AliasChoices(
|
|
184
|
+
"available_commands",
|
|
185
|
+
"availableCommands",
|
|
186
|
+
"supported_commands",
|
|
187
|
+
"supportedCommands",
|
|
188
|
+
),
|
|
189
|
+
)
|
|
125
190
|
dashboard: RuntimeEntityDashboardResponse | None = None
|
|
126
191
|
metadata: dict[str, Any] = Field(default_factory=dict)
|
|
127
192
|
|
{piphi_runtime_kit_python-0.4.1.dist-info → piphi_runtime_kit_python-0.4.2.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: piphi-runtime-kit-python
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.2
|
|
4
4
|
Summary: PiPhi Network runtime integration helpers
|
|
5
5
|
Keywords: piphi,runtime,integration,iot
|
|
6
6
|
Author-Email: KelvinSan <support@piphi.network>
|
|
@@ -362,15 +362,15 @@ async def health():
|
|
|
362
362
|
async def config(payload: DemoConfig, request: Request):
|
|
363
363
|
sync_runtime_auth_from_fastapi_payload(starter.runtime, request, payload)
|
|
364
364
|
typed_payload = validate_typed_config(payload, DemoConfig)
|
|
365
|
+
identity = build_runtime_identity(typed_payload)
|
|
365
366
|
starter.registry.set(
|
|
366
367
|
typed_payload.id,
|
|
367
368
|
{
|
|
368
|
-
|
|
369
|
-
"device_id": typed_payload.device_id or typed_payload.id,
|
|
369
|
+
**identity,
|
|
370
370
|
"host": typed_payload.host,
|
|
371
371
|
},
|
|
372
372
|
)
|
|
373
|
-
return build_config_apply_response(config_id=
|
|
373
|
+
return build_config_apply_response(config_id=identity["config_id"])
|
|
374
374
|
|
|
375
375
|
|
|
376
376
|
@app.post("/telemetry/example")
|
{piphi_runtime_kit_python-0.4.1.dist-info → piphi_runtime_kit_python-0.4.2.dist-info}/RECORD
RENAMED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
piphi_runtime_kit_python-0.4.
|
|
2
|
-
piphi_runtime_kit_python-0.4.
|
|
3
|
-
piphi_runtime_kit_python-0.4.
|
|
4
|
-
piphi_runtime_kit_python-0.4.
|
|
5
|
-
piphi_runtime_kit_python/__init__.py,sha256=
|
|
1
|
+
piphi_runtime_kit_python-0.4.2.dist-info/METADATA,sha256=th_AhsVfZ_at7LDyKQv7ZA1EVxiasOUwoSdTxQvdulI,30849
|
|
2
|
+
piphi_runtime_kit_python-0.4.2.dist-info/WHEEL,sha256=Z36eTX6lG3PITRleSd5hAZHCcz52yg3c0JQVxKBbLW0,90
|
|
3
|
+
piphi_runtime_kit_python-0.4.2.dist-info/entry_points.txt,sha256=6OYgBcLyFCUgeqLgnvMyOJxPCWzgy7se4rLPKtNonMs,34
|
|
4
|
+
piphi_runtime_kit_python-0.4.2.dist-info/licenses/LICENSE,sha256=pS6szQI4X7qAin1ODdoDp-XwZvsFy6ZZ28-JAwGHgzo,1070
|
|
5
|
+
piphi_runtime_kit_python/__init__.py,sha256=P8yx6C1P88xuXWuf3D58d5zhUD-pprhBhbVeyNbDaJQ,6013
|
|
6
6
|
piphi_runtime_kit_python/adapters/__init__.py,sha256=3jBhPZSBN3Qo7MKHlxAol2jPU3cK23BXHR2oTlircsw,361
|
|
7
7
|
piphi_runtime_kit_python/adapters/fastapi.py,sha256=1QcOBYprg6AmQVrkI8g61NIelBB_7BTbdvNaMvG2-s8,2098
|
|
8
8
|
piphi_runtime_kit_python/fastapi.py,sha256=OZ-ds2-g32kB4YkF90D5bM4vVVjpOWPtrNC-WdhDNyo,361
|
|
@@ -12,16 +12,17 @@ piphi_runtime_kit_python/runtime/config_sync.py,sha256=IzsH5AGxnISISWx8OYfNMTk2O
|
|
|
12
12
|
piphi_runtime_kit_python/runtime/configuration.py,sha256=4kkoJeENOhJHeNvC9QDu81ejDJUQJG7S5GmQG1sv3YQ,3631
|
|
13
13
|
piphi_runtime_kit_python/runtime/context.py,sha256=CwXgrivciBd7eTREn0u0zjqkDPy6VthASW-gsoZqCTg,1109
|
|
14
14
|
piphi_runtime_kit_python/runtime/discovery.py,sha256=uH6rJ4BnLVukTCxu2QwvN8yJhsI_fcT29VEat62oBcY,2274
|
|
15
|
-
piphi_runtime_kit_python/runtime/dispatch.py,sha256=
|
|
15
|
+
piphi_runtime_kit_python/runtime/dispatch.py,sha256=QcbA9B5izyyg0znlKHq94dbr-oqHVxKW2LCjrQKYfkY,7341
|
|
16
16
|
piphi_runtime_kit_python/runtime/errors.py,sha256=_mjqmJLsdM5NfrTwb6YFkhheqPfn6Df-QtAKgl9U6QU,4120
|
|
17
17
|
piphi_runtime_kit_python/runtime/events.py,sha256=JcvrTZlJ-vgY237jTDVOAVTbSxbcuh9u2QCdOGyuduA,6543
|
|
18
18
|
piphi_runtime_kit_python/runtime/health.py,sha256=9YO0K_UCJKTe6uSFLgb1kStr5dAgtIUc8Ha0dnRi2vA,1880
|
|
19
|
+
piphi_runtime_kit_python/runtime/identity.py,sha256=cth0_QHR9R5LTdp-6DPD1IhM8cYJT5HB1OUQYW7kLGs,2762
|
|
19
20
|
piphi_runtime_kit_python/runtime/lifespan.py,sha256=mVSdZZAS66xlcnlzAwkztFjzw_l2pyLrJqULJsb0Ezk,2850
|
|
20
21
|
piphi_runtime_kit_python/runtime/mqtt.py,sha256=JKMN5zxg1BcOidu7TaYnuRD3HuoAJ_WcvXMTTSlAteo,6069
|
|
21
|
-
piphi_runtime_kit_python/runtime/registry.py,sha256=
|
|
22
|
+
piphi_runtime_kit_python/runtime/registry.py,sha256=8rKLCWt1_0SlDm3TepEUGDliOhVEDTv_zYR0kxLpSHM,3373
|
|
22
23
|
piphi_runtime_kit_python/runtime/starter.py,sha256=j5C4GOOcRHNLJ-HYu8fmf3bE00baDOzAfuq1MefT-Jg,4651
|
|
23
24
|
piphi_runtime_kit_python/runtime/state.py,sha256=4xvQGTT59DF9rXHAtM3kDyV_UGg2a9tLPvGiCp_PFMc,674
|
|
24
25
|
piphi_runtime_kit_python/runtime/tasks.py,sha256=gMd-2K96jMU8tCPvI12xdWxuyNt5gsLDss2QWOoM94k,1241
|
|
25
26
|
piphi_runtime_kit_python/runtime/telemetry.py,sha256=RN6SFrhmAZ7aJLyioQMBzJEFsxQgOjjA1pV5qNeaR4E,4279
|
|
26
|
-
piphi_runtime_kit_python/schemas.py,sha256=
|
|
27
|
-
piphi_runtime_kit_python-0.4.
|
|
27
|
+
piphi_runtime_kit_python/schemas.py,sha256=LGz53OHmWwUEQb_nHbVBgRDGVGowJPT53S2P7otP3lo,9073
|
|
28
|
+
piphi_runtime_kit_python-0.4.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|