Added live value and signal descriptor fetching

Live values are stored in the core and their fetch is relatively cheap
as it only requires locking the core live values lock

Signal descriptors are a much heavier call as they query the connector
registry and trigger an O(n) search throughout the different endpoints,
this method is not meant to be used heavily as it requires locking
multiple locks and handling alot of data, this method is meant to be
called once to retreive a list of signal descriptors that the user can
then store and use to reference values against in their frontend code
This commit is contained in:
2026-08-06 11:08:02 +01:00
parent 561f42aca2
commit 87c88c3f3d
3 changed files with 57 additions and 0 deletions
+21
View File
@@ -19,6 +19,7 @@ from dynalab_core.protocols.common import VersionDescriptor
from dynalab_core.protocols.json.server import JsonServer
from dynalab_core.protocols.packets import ProtocolMessage
from dynalab_core.protocols.packets.data import ValueDescriptor
from dynalab_core.protocols.packets.handshake import SignalDescriptor
from dynalab_core.values import Value
@@ -102,6 +103,26 @@ class Core:
extra={"event": "core.stopped", "core_state": self._state},
)
def get_signal_descriptor(self, signal_id: UUID) -> SignalDescriptor | None:
return self._connector_registry.get_signal_descriptor(signal_id)
def get_all_signal_descriptors(self) -> list[SignalDescriptor]:
return self._connector_registry.get_all_signal_descriptors()
def get_live_value(self, signal_id: UUID) -> float | None:
with self._live_values_lock:
live_value = self._live_values.get(signal_id)
if live_value is None:
return None
return live_value.get()
def get_all_live_values(self) -> dict[UUID, float]:
with self._live_values_lock:
live_values = list(self._live_values.items())
return {signal_id: value.get() for signal_id, value in live_values}
def _input_worker(self) -> None:
while not self._stop_event.is_set():
try:
+34
View File
@@ -20,6 +20,7 @@ from dynalab_core.protocols.packets.handshake import (
ConnectorHello,
HandshakeAccepted,
HandshakeRejected,
SignalDescriptor,
)
from dynalab_core.protocols.packets.heartbeat import Heartbeat
@@ -111,6 +112,16 @@ class ConnectorEndpoint:
def uuid(self) -> UUID:
return self._connector_hello.connector_uuid
def get_signal_descriptor(self, signal_id: UUID) -> SignalDescriptor | None:
for signal in self._connector_hello.signals:
if signal.id == signal_id:
return signal
return None
def get_all_signal_descriptors(self) -> list[SignalDescriptor]:
return self._connector_hello.signals
def put_ingress_packet(self, packet: ProtocolMessage) -> None:
try:
self._packet_ingress_queue.put_nowait(packet)
@@ -393,6 +404,29 @@ class ConnectorRegistry:
with self._lock:
return self._endpoints.get(connector_uuid)
def get_signal_descriptor(self, signal_id: UUID) -> SignalDescriptor | None:
with self._lock:
endpoints = list(self._endpoints.items())
for _, endpoint in endpoints:
signal = endpoint.get_signal_descriptor(signal_id)
if signal is not None:
return signal
return None
def get_all_signal_descriptors(self) -> list[SignalDescriptor]:
with self._lock:
endpoints = list(self._endpoints.items())
signals: list[SignalDescriptor] = []
for _, endpoint in endpoints:
endpoint_signals = endpoint.get_all_signal_descriptors()
for signal in endpoint_signals:
signals.append(signal)
return signals
def stop(self) -> None:
with self._lock:
endpoints = tuple(self._endpoints.values())
+2
View File
@@ -23,6 +23,8 @@ dl_core.start()
try:
while True:
dl_core.wait(1)
values = dl_core.get_all_live_values()
log.debug(f"Core values: {values}")
except KeyboardInterrupt:
log.info("Received keyboard interrupt")
dl_core.stop()