From 1b27b89ca0e0266a919f8630a6d864257eefbea1 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Thu, 19 Mar 2026 11:15:54 -0400 Subject: [PATCH] feat(infra): scaffold LmxFakeProxy project with proto and test project --- infra/lmxfakeproxy/LmxFakeProxy.csproj | 17 ++ infra/lmxfakeproxy/Program.cs | 5 + infra/lmxfakeproxy/Protos/scada.proto | 166 ++++++++++++++++++ .../LmxFakeProxy.Tests.csproj | 20 +++ 4 files changed, 208 insertions(+) create mode 100644 infra/lmxfakeproxy/LmxFakeProxy.csproj create mode 100644 infra/lmxfakeproxy/Program.cs create mode 100644 infra/lmxfakeproxy/Protos/scada.proto create mode 100644 infra/lmxfakeproxy/tests/LmxFakeProxy.Tests/LmxFakeProxy.Tests.csproj diff --git a/infra/lmxfakeproxy/LmxFakeProxy.csproj b/infra/lmxfakeproxy/LmxFakeProxy.csproj new file mode 100644 index 0000000..1eaf063 --- /dev/null +++ b/infra/lmxfakeproxy/LmxFakeProxy.csproj @@ -0,0 +1,17 @@ + + + net10.0 + LmxFakeProxy + enable + enable + + + + + + + + + + + diff --git a/infra/lmxfakeproxy/Program.cs b/infra/lmxfakeproxy/Program.cs new file mode 100644 index 0000000..933d130 --- /dev/null +++ b/infra/lmxfakeproxy/Program.cs @@ -0,0 +1,5 @@ +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddGrpc(); +var app = builder.Build(); +app.MapGet("/", () => "LmxFakeProxy is running"); +app.Run(); diff --git a/infra/lmxfakeproxy/Protos/scada.proto b/infra/lmxfakeproxy/Protos/scada.proto new file mode 100644 index 0000000..fc327aa --- /dev/null +++ b/infra/lmxfakeproxy/Protos/scada.proto @@ -0,0 +1,166 @@ +syntax = "proto3"; + +option csharp_namespace = "LmxFakeProxy.Grpc"; + +package scada; + +// The SCADA service definition +service ScadaService { + // Connection management + rpc Connect(ConnectRequest) returns (ConnectResponse); + rpc Disconnect(DisconnectRequest) returns (DisconnectResponse); + rpc GetConnectionState(GetConnectionStateRequest) returns (GetConnectionStateResponse); + + // Read operations + rpc Read(ReadRequest) returns (ReadResponse); + rpc ReadBatch(ReadBatchRequest) returns (ReadBatchResponse); + + // Write operations + rpc Write(WriteRequest) returns (WriteResponse); + rpc WriteBatch(WriteBatchRequest) returns (WriteBatchResponse); + rpc WriteBatchAndWait(WriteBatchAndWaitRequest) returns (WriteBatchAndWaitResponse); + + // Subscription operations (server streaming) - now streams VtqMessage directly + rpc Subscribe(SubscribeRequest) returns (stream VtqMessage); + + // Authentication + rpc CheckApiKey(CheckApiKeyRequest) returns (CheckApiKeyResponse); +} + +// === CONNECTION MESSAGES === + +message ConnectRequest { + string client_id = 1; + string api_key = 2; +} + +message ConnectResponse { + bool success = 1; + string message = 2; + string session_id = 3; +} + +message DisconnectRequest { + string session_id = 1; +} + +message DisconnectResponse { + bool success = 1; + string message = 2; +} + +message GetConnectionStateRequest { + string session_id = 1; +} + +message GetConnectionStateResponse { + bool is_connected = 1; + string client_id = 2; + int64 connected_since_utc_ticks = 3; +} + +// === VTQ MESSAGE === + +message VtqMessage { + string tag = 1; + string value = 2; + int64 timestamp_utc_ticks = 3; + string quality = 4; // "Good", "Uncertain", "Bad" +} + +// === READ MESSAGES === + +message ReadRequest { + string session_id = 1; + string tag = 2; +} + +message ReadResponse { + bool success = 1; + string message = 2; + VtqMessage vtq = 3; +} + +message ReadBatchRequest { + string session_id = 1; + repeated string tags = 2; +} + +message ReadBatchResponse { + bool success = 1; + string message = 2; + repeated VtqMessage vtqs = 3; +} + +// === WRITE MESSAGES === + +message WriteRequest { + string session_id = 1; + string tag = 2; + string value = 3; +} + +message WriteResponse { + bool success = 1; + string message = 2; +} + +message WriteItem { + string tag = 1; + string value = 2; +} + +message WriteResult { + string tag = 1; + bool success = 2; + string message = 3; +} + +message WriteBatchRequest { + string session_id = 1; + repeated WriteItem items = 2; +} + +message WriteBatchResponse { + bool success = 1; + string message = 2; + repeated WriteResult results = 3; +} + +message WriteBatchAndWaitRequest { + string session_id = 1; + repeated WriteItem items = 2; + string flag_tag = 3; + string flag_value = 4; + int32 timeout_ms = 5; + int32 poll_interval_ms = 6; +} + +message WriteBatchAndWaitResponse { + bool success = 1; + string message = 2; + repeated WriteResult write_results = 3; + bool flag_reached = 4; + int32 elapsed_ms = 5; +} + +// === SUBSCRIPTION MESSAGES === + +message SubscribeRequest { + string session_id = 1; + repeated string tags = 2; + int32 sampling_ms = 3; +} + +// Note: Subscribe RPC now streams VtqMessage directly (defined above) + +// === AUTHENTICATION MESSAGES === + +message CheckApiKeyRequest { + string api_key = 1; +} + +message CheckApiKeyResponse { + bool is_valid = 1; + string message = 2; +} diff --git a/infra/lmxfakeproxy/tests/LmxFakeProxy.Tests/LmxFakeProxy.Tests.csproj b/infra/lmxfakeproxy/tests/LmxFakeProxy.Tests/LmxFakeProxy.Tests.csproj new file mode 100644 index 0000000..580a665 --- /dev/null +++ b/infra/lmxfakeproxy/tests/LmxFakeProxy.Tests/LmxFakeProxy.Tests.csproj @@ -0,0 +1,20 @@ + + + net10.0 + LmxFakeProxy.Tests + enable + enable + false + + + + + + + + + + + + +