From 53394218f49fe0425161456d329d17599835626e Mon Sep 17 00:00:00 2001 From: Sylvain Renault Date: Fri, 16 Aug 2024 12:08:42 +0200 Subject: [PATCH] Client/module registration for websockets. WIP class to manage clients/modules. --- openapi | 1 + .../ETSI.ARF.OpenAPI.WorldAnalysis/Dockerfile | 8 +-- .../ControllersImpl/CapabilitiesImpl.cs | 11 +++- .../ETSI-ARF/ControllersImpl/PoseImpl.cs | 2 +- .../ControllersImpl/WebSocketController.cs | 61 +++++++++++++++---- .../ETSI-ARF/WorldAnalysisModules.cs | 46 ++++++++++++++ 6 files changed, 109 insertions(+), 20 deletions(-) create mode 160000 openapi create mode 100644 server/worldanalysis/src/ETSI.ARF.OpenAPI.WorldAnalysis/ETSI-ARF/WorldAnalysisModules.cs diff --git a/openapi b/openapi new file mode 160000 index 0000000..073fd72 --- /dev/null +++ b/openapi @@ -0,0 +1 @@ +Subproject commit 073fd7213fd9e6ebc2f8a47d628a650de30c8bc4 diff --git a/server/worldanalysis/src/ETSI.ARF.OpenAPI.WorldAnalysis/Dockerfile b/server/worldanalysis/src/ETSI.ARF.OpenAPI.WorldAnalysis/Dockerfile index 1203a89..76f44e2 100644 --- a/server/worldanalysis/src/ETSI.ARF.OpenAPI.WorldAnalysis/Dockerfile +++ b/server/worldanalysis/src/ETSI.ARF.OpenAPI.WorldAnalysis/Dockerfile @@ -1,21 +1,21 @@ #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. # Container we use for final publish -FROM mcr.microsoft.com/dotnet/core/aspnet:5.0-buster-slim AS base +FROM mcr.microsoft.com/dotnet/aspnet:5.0-buster-slim AS base WORKDIR /app EXPOSE 80 EXPOSE 443 # Build container -FROM mcr.microsoft.com/dotnet/core/sdk:5.0-buster AS build +FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim AS build # Copy the code into the container WORKDIR /src -COPY ["src/ETSI.ARF.OpenAPI.WorldAnalysis/ETSI.ARF.OpenAPI.WorldAnalysis.csproj", "ETSI.ARF.OpenAPI.WorldAnalysis/"] +COPY ["ETSI.ARF.OpenAPI.WorldAnalysis.csproj", "ETSI.ARF.OpenAPI.WorldAnalysis/"] # NuGet restore RUN dotnet restore "ETSI.ARF.OpenAPI.WorldAnalysis/ETSI.ARF.OpenAPI.WorldAnalysis.csproj" -COPY ["src/ETSI.ARF.OpenAPI.WorldAnalysis/", "ETSI.ARF.OpenAPI.WorldAnalysis/"] +COPY [".", "ETSI.ARF.OpenAPI.WorldAnalysis/"] # Build the API WORKDIR "ETSI.ARF.OpenAPI.WorldAnalysis" diff --git a/server/worldanalysis/src/ETSI.ARF.OpenAPI.WorldAnalysis/ETSI-ARF/ControllersImpl/CapabilitiesImpl.cs b/server/worldanalysis/src/ETSI.ARF.OpenAPI.WorldAnalysis/ETSI-ARF/ControllersImpl/CapabilitiesImpl.cs index 648b36f..f5b295d 100644 --- a/server/worldanalysis/src/ETSI.ARF.OpenAPI.WorldAnalysis/ETSI-ARF/ControllersImpl/CapabilitiesImpl.cs +++ b/server/worldanalysis/src/ETSI.ARF.OpenAPI.WorldAnalysis/ETSI-ARF/ControllersImpl/CapabilitiesImpl.cs @@ -55,14 +55,21 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers { // Get all capabilities from all anchors/trackables // test + EncodingInformationStructure enc = new EncodingInformationStructure(); + enc.DataFormat = EncodingInformationStructure.DataFormatEnum.OTHEREnum; + enc.VarVersion = "12345"; + Capability capability = new Capability(); + capability.TrackableType = TrackableType.FIDUCIALMARKEREnum; + capability.EncodingInformation = enc; + capability.Accuracy = 1; capability.Framerate = 24; capability.Latency = 0; - capability.TrackableType = TrackableType.FIDUCIALMARKEREnum; // Create list List capabilities = new List(); - capabilities.Add(capability); + //capabilities.Add(capability); + capabilities.AddRange(WorldAnalysisModules.Singleton.GetCapabilities()); // Create repsonse object GetCapabilities200Response response = new GetCapabilities200Response(); diff --git a/server/worldanalysis/src/ETSI.ARF.OpenAPI.WorldAnalysis/ETSI-ARF/ControllersImpl/PoseImpl.cs b/server/worldanalysis/src/ETSI.ARF.OpenAPI.WorldAnalysis/ETSI-ARF/ControllersImpl/PoseImpl.cs index 1fbaa52..3489e85 100644 --- a/server/worldanalysis/src/ETSI.ARF.OpenAPI.WorldAnalysis/ETSI-ARF/ControllersImpl/PoseImpl.cs +++ b/server/worldanalysis/src/ETSI.ARF.OpenAPI.WorldAnalysis/ETSI-ARF/ControllersImpl/PoseImpl.cs @@ -88,7 +88,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers SubscribeToPose200Response response = new SubscribeToPose200Response(); response.Target = subscribeToPoseRequest.Target; response.Mode = subscribeToPoseRequest.Mode[0]; - response.WebhookUrl = subscribeToPoseRequest.WebhookUrl; + response.WebhookUrl = ""; response.WebsocketUrl = Request.Host.ToString(); ; return new ObjectResult(response); diff --git a/server/worldanalysis/src/ETSI.ARF.OpenAPI.WorldAnalysis/ETSI-ARF/ControllersImpl/WebSocketController.cs b/server/worldanalysis/src/ETSI.ARF.OpenAPI.WorldAnalysis/ETSI-ARF/ControllersImpl/WebSocketController.cs index f0c81d3..1ad1076 100644 --- a/server/worldanalysis/src/ETSI.ARF.OpenAPI.WorldAnalysis/ETSI-ARF/ControllersImpl/WebSocketController.cs +++ b/server/worldanalysis/src/ETSI.ARF.OpenAPI.WorldAnalysis/ETSI-ARF/ControllersImpl/WebSocketController.cs @@ -30,11 +30,12 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Http; using Swashbuckle.AspNetCore.Annotations; using Swashbuckle.AspNetCore.SwaggerGen; +using Newtonsoft.Json; using ETSI.ARF.OpenAPI.WorldAnalysis.Models; #pragma warning disable CS1591 // Fehlendes XML-Kommentar für öffentlich sichtbaren Typ oder Element -namespace ETSI.ARF.OpenAPI.WorldStorage.Services +namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers { // // ETSI-ARF World Analysis WebSocket implementation @@ -56,7 +57,7 @@ namespace ETSI.ARF.OpenAPI.WorldStorage.Services if (webSocket.State == WebSocketState.Connecting) { - // Response an OK message + // Response an OK message? } else if (webSocket.State == WebSocketState.Open) { @@ -97,7 +98,7 @@ namespace ETSI.ARF.OpenAPI.WorldStorage.Services timeCnt--; if (timeCnt < 0) { - await SendText(webSocket, "Stop"); + await SendText(webSocket, "TimeStop"); break; } else await SendText(webSocket, message); @@ -120,7 +121,7 @@ namespace ETSI.ARF.OpenAPI.WorldStorage.Services timeCnt--; if (timeCnt < 0) { - await SendText(webSocket, "Stop"); + await SendText(webSocket, "PoseStop"); break; } else @@ -147,30 +148,49 @@ namespace ETSI.ARF.OpenAPI.WorldStorage.Services } else if (webSocket.State == WebSocketState.Closed || webSocket.State == WebSocketState.Aborted) { + if (WorldAnalysisModules.Singleton.modules.Contains(currentModule)) WorldAnalysisModules.Singleton.modules.Remove(currentModule); + if (WorldAnalysisModules.Singleton.clients.Contains(currentClient)) WorldAnalysisModules.Singleton.clients.Remove(currentClient); + currentClient = null; + currentModule = null; break; } Thread.Sleep(250); } } + private Module currentModule; + private Client currentClient; + private async void OnReceiveText(WebSocket webSocket, string msg) { if (firstTime) { // Register the client/module - if (msg.ToLower().StartsWith("module:")) + if (msg.StartsWith("Module:")) { registered = true; firstTime = false; currentName = msg.Split(':')[1]; - await SendText(webSocket, "ARF World Analysis Server: You are now registered as a module: " + currentName); + if (currentModule == null && currentClient == null) + { + currentModule = new Module(); + currentModule.name = currentName; + WorldAnalysisModules.Singleton.modules.Add(currentModule); + await SendText(webSocket, "ARF World Analysis Server: You are now registered as a module: " + currentName); + } } - else if (msg.ToLower().StartsWith("client:")) + else if (msg.StartsWith("Client:")) { registered = true; firstTime = false; currentName = msg.Split(':')[1]; - await SendText(webSocket, "ARF World Analysis Server: You are now registered as a client: " + currentName); + if (currentModule == null && currentClient == null) + { + currentClient = new Client(); + currentClient.name = currentName; + WorldAnalysisModules.Singleton.clients.Add(currentClient); + await SendText(webSocket, "ARF World Analysis Server: You are now registered as a client: " + currentName); + } } else { @@ -180,25 +200,40 @@ namespace ETSI.ARF.OpenAPI.WorldStorage.Services } else if (registered) { - if (msg.ToLower().StartsWith("startsendingpose")) + if (msg.StartsWith("StartSendingPose")) { if (msg.Contains(':')) timeCnt = int.Parse(msg.Split(':')[1]); else timeCnt = 3; await SendPose(webSocket); - } - else if (msg.ToLower().StartsWith("time")) + } + else if (msg.StartsWith("Time")) { if (msg.Contains(':')) timeCnt = int.Parse(msg.Split(':')[1]); else timeCnt = 3; await SendTime(webSocket); } - else if (msg.ToLower() == "unregister") + else if (msg.StartsWith("Capabilities")) + { + // Client is sending its capabilities + string[] str_cap = msg.Split('='); + Capability _c = JsonConvert.DeserializeObject(str_cap[1]); + if (currentModule != null) currentModule.capabilities.Add(_c); + } + else if (msg == "UnregisterClient") { // Unregister client/user currentName = ""; firstTime = true; registered = false; - await SendText(webSocket, "Stop"); + await SendText(webSocket, "SessionStop"); + } + else if (msg == "Idle") + { + await SendText(webSocket, "Idle"); + } + else if (msg == "Busy") + { + await SendText(webSocket, "Busy"); } else { diff --git a/server/worldanalysis/src/ETSI.ARF.OpenAPI.WorldAnalysis/ETSI-ARF/WorldAnalysisModules.cs b/server/worldanalysis/src/ETSI.ARF.OpenAPI.WorldAnalysis/ETSI-ARF/WorldAnalysisModules.cs new file mode 100644 index 0000000..951472f --- /dev/null +++ b/server/worldanalysis/src/ETSI.ARF.OpenAPI.WorldAnalysis/ETSI-ARF/WorldAnalysisModules.cs @@ -0,0 +1,46 @@ +using ETSI.ARF.OpenAPI.WorldAnalysis.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +#pragma warning disable CS1591 // Fehlendes XML-Kommentar für öffentlich sichtbaren Typ oder Element +namespace ETSI.ARF.OpenAPI.WorldAnalysis +{ + // For management of WA modules + public class Module + { + public string name; + public List capabilities = new List(); + } + + // For management of WA clinet (e.g. Unity client) + public class Client + { + public string name; + public string session; + + } + + public class WorldAnalysisModules + { + static public WorldAnalysisModules Singleton = new WorldAnalysisModules(); + + public List modules = new List(); + public List clients = new List(); + + // todo + // Manage the sessions and modules + // get capabilities of all modules + public List GetCapabilities() + { + List list = new List(); + foreach (var item in modules) + { + list.AddRange(item.capabilities); + } + return list; + } + } +} +#pragma warning restore CS1591 // Fehlendes XML-Kommentar für öffentlich sichtbaren Typ oder Element -- GitLab