Working data ingress into live data buffer

This commit is contained in:
2026-07-08 12:30:47 +01:00
parent 5887e0d0a0
commit 05bc8bdf25
7 changed files with 131 additions and 55 deletions

View File

@@ -2,6 +2,8 @@
from __future__ import annotations
import asyncio
from random import random
from time import monotonic
import uuid
from dynalab_protocol.models import (
ConnectorHello,
@@ -10,6 +12,7 @@ from dynalab_protocol.models import (
HandshakeRejected,
Heartbeat,
SignalDescriptor,
ValueDescriptor,
machine_timestamp_ms,
)
from dynalab_protocol.wire import read_message, write_message
@@ -17,9 +20,79 @@ from dynalab_protocol.wire import read_message, write_message
HOST = "127.0.0.1"
PORT = 8765
RETRY_DELAY_SECONDS = 2
async def main() -> None:
def build_signals() -> list[SignalDescriptor]:
"""Describe the signals this example connector exposes to DynaLab."""
return [
SignalDescriptor(
id=uuid.uuid4(), name="lambda", type="number", min_value=0, max_value=5
),
SignalDescriptor(
id=uuid.uuid4(),
name="torque",
type="number",
min_value=0,
max_value=10,
unit="Nm",
),
SignalDescriptor(
id=uuid.uuid4(),
name="RPM",
type="number",
min_value=0,
max_value=6000,
unit="RPM",
),
SignalDescriptor(
id=uuid.uuid4(),
name="temperature",
type="number",
min_value=0,
max_value=120,
unit="°C",
),
SignalDescriptor(
id=uuid.uuid4(),
name="voltage",
type="number",
min_value=0,
max_value=20,
unit="V",
),
SignalDescriptor(
id=uuid.uuid4(),
name="current",
type="number",
min_value=0,
max_value=50,
unit="A",
),
]
async def _value_sender(
writer: asyncio.StreamWriter, connector_hello: ConnectorHello
) -> None:
last_value_send = monotonic()
while True:
if monotonic() > last_value_send + 0.1:
multipliers: list[int] = [5, 10, 6000, 120, 20, 50]
for i in range(6):
random_val = random() * multipliers[i]
value = ValueDescriptor(
signal_id=connector_hello.signals[i].id, value=random_val
)
await write_message(writer, value)
last_value_send = monotonic()
else:
await asyncio.sleep(0.05)
async def run_connector_session() -> None:
"""Open one connection to DynaLab and run the connector protocol."""
reader, writer = await asyncio.open_connection(HOST, PORT)
dynalab_hello: DynaLabHello
@@ -29,6 +102,7 @@ async def main() -> None:
print(f"Connected to DynaLab at {peer}")
try:
# DynaLab starts the protocol by introducing itself to the connector.
message = await asyncio.wait_for(read_message(reader), timeout=5.0)
if not isinstance(message, DynaLabHello):
@@ -37,47 +111,16 @@ async def main() -> None:
dynalab_hello = message
print(f"Received DynaLab Hello\n {dynalab_hello}")
signals: list[SignalDescriptor] = [
SignalDescriptor(
id=uuid.uuid4(), name="lambda", type="number", min_value=0, max_value=5
),
SignalDescriptor(
id=uuid.uuid4(), name="torque", type="number", min_value=0, max_value=10
),
SignalDescriptor(
id=uuid.uuid4(), name="RPM", type="number", min_value=0, max_value=6000
),
SignalDescriptor(
id=uuid.uuid4(),
name="temperature",
type="number",
min_value=0,
max_value=120,
),
SignalDescriptor(
id=uuid.uuid4(),
name="voltage",
type="number",
min_value=0,
max_value=20,
),
SignalDescriptor(
id=uuid.uuid4(),
name="current",
type="number",
min_value=0,
max_value=50,
),
]
# Reply with the connector identity and signal list.
connector_hello = ConnectorHello(
connector_uuid=uuid.uuid4(),
connector_name="Minimal Connector",
connector_version="a0.0.1",
signals=signals,
signals=build_signals(),
)
await write_message(writer, connector_hello)
# DynaLab accepts or rejects the connector after validating the hello.
message = await asyncio.wait_for(read_message(reader), timeout=5.0)
if isinstance(message, HandshakeAccepted):
@@ -87,6 +130,8 @@ async def main() -> None:
print(f"Connector handshake rejected: {message.reason}")
return
value_task = asyncio.create_task(_value_sender(writer, connector_hello))
# Keep the connection alive by returning heartbeat messages.
while True:
message = await read_message(reader)
print(f"Received {message}")
@@ -100,11 +145,25 @@ async def main() -> None:
raise
finally:
value_task.cancel()
print("Disconnecting")
writer.close()
await writer.wait_closed()
async def main() -> None:
while True:
try:
await run_connector_session()
return
except ConnectionError as error:
print(
f"Connection error: {error}. "
f"Retrying in {RETRY_DELAY_SECONDS} seconds..."
)
await asyncio.sleep(RETRY_DELAY_SECONDS)
if __name__ == "__main__":
try:
asyncio.run(main())