diff --git a/openapi b/openapi
index b639a02180c2b5e301c77483b3a2fa645ba94169..073fd7213fd9e6ebc2f8a47d628a650de30c8bc4 160000
--- a/openapi
+++ b/openapi
@@ -1 +1 @@
-Subproject commit b639a02180c2b5e301c77483b3a2fa645ba94169
+Subproject commit 073fd7213fd9e6ebc2f8a47d628a650de30c8bc4
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 f9c1a3543df47330a2fc2d11b904b5e75c1f85a0..4638d5c7df96786128abcc49291f699338163b95 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
@@ -53,13 +53,16 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers
         /// </summary>
         public override IActionResult GetCapabilities([FromHeader (Name = "token")]string token, [FromHeader (Name = "sessionID")]string sessionID)
         {
-            // todo: compare token and sessionID
+            if (!Startup.IsAccessGranted(token)) return StatusCode(511, new Error() { Message = "Invalid token!" });
+
+            // todo: compare sessionID
 
             // Get all capabilities from all anchors/trackables
+            // Info: Capabilities are collected after a module is connected via websockets
 
             // Create list
             List<Capability> capabilitiesList = new List<Capability>();
-            capabilitiesList.AddRange(WorldAnalysisModules.Singleton.GetCapabilities());
+            capabilitiesList.AddRange(WorldAnalysisConnections.Singleton.GetCapabilities());
 
             // Create response object
             GetCapabilities200Response response = new GetCapabilities200Response();
@@ -73,11 +76,13 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers
         /// </summary>
         public override IActionResult GetSupport([FromRoute (Name = "trackableOrAnchorUUID")][Required]Guid trackableOrAnchorUUID, [FromHeader (Name = "token")]string token, [FromHeader (Name = "sessionID")]string sessionID)
         {
-            // todo: compare token and sessionID
+            if (!Startup.IsAccessGranted(token)) return StatusCode(511, new Error() { Message = "Invalid token!" });
+
+            // todo: compare sessionID
 
             // Create list
             List<Capability> capabilitiesList = new List<Capability>();
-            capabilitiesList.AddRange(WorldAnalysisModules.Singleton.GetCapabilitiesFromUuid(trackableOrAnchorUUID));
+            capabilitiesList.AddRange(WorldAnalysisConnections.Singleton.GetCapabilitiesFromUuid(trackableOrAnchorUUID));
 
             // Create response object
             GetSupport200Response response = new GetSupport200Response();
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 058e38806c8618f1b8a64de2238996e8eef5c7ac..44606416aab46dfd8512ffebd5068f2ada13de84 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
@@ -53,11 +53,13 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers
         /// </summary>
         public override IActionResult ConfigureFramerate([FromBody] PoseConfiguration poseConfiguration, [FromHeader(Name = "token")] string token, [FromHeader(Name = "sessionID")] string sessionID)
         {
-            // todo: compare token and sessionID
+            if (!Startup.IsAccessGranted(token)) return StatusCode(511, new Error() { Message = "Invalid token!" });
+
+            // todo: compare sessionID
 
             // Notify the modules that the client need a new framerate
-            WorldAnalysisModules.Singleton.ConfigureFramerate(poseConfiguration);
-            return StatusCode(200, "Ok.");
+            bool result = WorldAnalysisConnections.Singleton.ConfigureFramerate(poseConfiguration);
+            return result ? StatusCode(200, "Ok.") : StatusCode(405, "Not supported.");
         }
 
         /// <summary>
@@ -65,11 +67,13 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers
         /// </summary>
         public override IActionResult GetPose([FromRoute(Name = "trackableOrAnchorUUID")][Required] Guid trackableOrAnchorUUID, [FromQuery(Name = "mode")][Required()] ModeWorldAnalysis mode, [FromHeader(Name = "token")] string token, [FromHeader(Name = "sessionID")] string sessionID)
         {
-            // todo: compare token and sessionID
+            if (!Startup.IsAccessGranted(token)) return StatusCode(511, new Error() { Message = "Invalid token!" });
+
+            // todo: compare sessionID
 
             // Request from the modules a new pose of a single UUID
             Pose result;
-            result = WorldAnalysisModules.Singleton.GetPose(trackableOrAnchorUUID, mode);
+            result = WorldAnalysisConnections.Singleton.GetPose(trackableOrAnchorUUID, mode);
             return new ObjectResult(result);
         }
 
@@ -78,13 +82,15 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers
         /// </summary>
         public override IActionResult GetPoses([FromQuery(Name = "uuid")][Required()] List<UuidAndMode> uuid, [FromHeader(Name = "token")] string token, [FromHeader(Name = "sessionID")] string sessionID)
         {
-            // todo: compare token and sessionID
+            if (!Startup.IsAccessGranted(token)) return StatusCode(511, new Error() { Message = "Invalid token!" });
+
+            // todo: compare sessionID
 
             // Request from the modules new poses from all UUIDs
             GetPoses200Response result = new GetPoses200Response();
             foreach (var item in uuid)
             {
-                result.Poses.Add(WorldAnalysisModules.Singleton.GetPose(item.Uuid, item.Mode));
+                result.Poses.Add(WorldAnalysisConnections.Singleton.GetPose(item.Uuid, item.Mode));
             }
             return new ObjectResult(result);
         }
@@ -101,10 +107,13 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers
 
         public struct SubscriptionInfo
         {
-            public Guid uuid;           // id of subscription (id is defined by the WA server)
-            public Guid uuidTarget;     // id trackable or anchor
-            public DateTime timeValidity;  //The duration of the validity of the subscription
+            public Guid uuidSub;           // id of subscription (id is defined by the WA server)
+
+            public SubscribeToPoseRequest subscription;
+            public string webSocket;
             public Pose pose;
+            public DateTime timeValidity;
+
             //public PoseCallback callback;
         }
 #pragma warning restore CS1591 // Fehlendes XML-Kommentar für öffentlich sichtbaren Typ oder Element
@@ -114,11 +123,26 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers
         /// </summary>
         public override IActionResult GetSubscription([FromRoute(Name = "subscriptionUUID")][Required] Guid subscriptionUUID, [FromHeader(Name = "token")] string token, [FromHeader(Name = "sessionID")] string sessionID)
         {
-            // todo: compare token and sessionID
+            if (!Startup.IsAccessGranted(token)) return StatusCode(511, new Error() { Message = "Invalid token!" });
 
-            // todo: search for a subscription and send it back
+            // todo: compare sessionID
 
-            return StatusCode(405, "Not supported yet!");
+            // todo: search for a subscription and send it back
+            foreach (var item in m_subscriptionsPoses)
+            {
+                if (item.Key == subscriptionUUID)
+                {
+                    SubscriptionSingle response = new SubscriptionSingle();
+                    response.Uuid = subscriptionUUID;
+                    response.Target = item.Value.subscription.Target;
+                    response.Mode = item.Value.pose.Mode;
+                    response.Validity = item.Value.timeValidity.Millisecond;
+                    response.WebhookUrl = item.Value.subscription.WebhookUrl;
+                    response.WebsocketUrl = item.Value.webSocket;
+                    return new ObjectResult(response);
+                }
+            }
+            return StatusCode(404, "Not found.");
         }
 
         /// <summary>
@@ -126,46 +150,67 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers
         /// </summary>
         public override IActionResult SubscribeToPose([FromBody] SubscribeToPoseRequest subscribeToPoseRequest, [FromHeader(Name = "token")] string token, [FromHeader(Name = "sessionID")] string sessionID)
         {
-            // todo: compare token and sessionID
+            // Simulation ON for STF669 pose calcualtion
+            string _token = token;
+            Guid parentUUID = Guid.Empty;
+            if (token.Contains(","))
+            {
+                _token = token.Split(',')[0];
+                parentUUID = new Guid(token.Split(',')[1]);
+            }
+
+            if (!Startup.IsAccessGranted(_token)) return StatusCode(511, new Error() { Message = "Invalid token!" });
+
+            // todo: compare sessionID
+
+            if (subscribeToPoseRequest.Targets != null && subscribeToPoseRequest.Targets.Count > 0)
+            {
+                return StatusCode(404, "Multiple subscriptions are not implemented (targets).");
+            }
+            else if (subscribeToPoseRequest.Modes != null && subscribeToPoseRequest.Modes.Count > 0)
+            {
+                return StatusCode(404, "Multiple subscriptions are not implemented (modes).");
+            }
 
             int validity = subscribeToPoseRequest.Validity; // todo: is to handle here or by the client?
 
+            SubscribeToPose200Response response = new SubscribeToPose200Response();
+            response.Validity = validity;
+            response.Uuid = Guid.NewGuid();
+            response.Target = subscribeToPoseRequest.Target;
+            response.Mode = subscribeToPoseRequest.Mode;
+            response.WebhookUrl = subscribeToPoseRequest.WebhookUrl;
+            response.WebsocketUrl = "";
+
+            // Send the websocket connection URL
+            if (string.IsNullOrEmpty(response.WebhookUrl))
+            {
+                // Notice: starting websocket server is done autom. by the client, when calling "URL:xxx/ws"
+                // Registering the client is done in the analysis module, so the websocket can send to it pose updates
+                response.WebsocketUrl = "wss://" + Request.Host.ToString() + "/ws";
+            }
+
             // We add the subscription
             SubscriptionInfo info = new SubscriptionInfo();
-            info.uuid = new Guid();
-            info.uuidTarget = subscribeToPoseRequest.Target;
+            info.uuidSub = response.Uuid;
+            info.webSocket = response.WebsocketUrl;
             info.timeValidity = DateTime.Now.AddMilliseconds(validity / 1000.0f);
+
             info.pose = new Pose();
-            info.pose.Mode = subscribeToPoseRequest.Mode;
-            m_subscriptionsPoses.Add(info.uuid, info);
+            info.pose.Mode = response.Mode;
 
-            // todo: handle multiple subscriptions ?
-            // subscribeToPoseRequest.Targets[]
-            // subscribeToPoseRequest.Modes[]
+            info.subscription = new SubscribeToPoseRequest();
+            info.subscription.Target = response.Target;
+            info.subscription.Mode = response.Mode;
+            info.subscription.Validity = response.Validity;
+            info.subscription.WebhookUrl = response.WebhookUrl;
 
+            m_subscriptionsPoses.Add(info.uuidSub, info);
+            
             // todo: inform the module(s) that the client will track an anchor/trackable and need the pose
             // todo: has the module to call GetRelocalizationInformation() then?!?
-            WorldAnalysisModules.Singleton.SubscribeToPose(info);
-
-            SubscribeToPose200Response response = new SubscribeToPose200Response();
-            response.Validity = validity;
-            response.Uuid = info.uuid;
-            response.Target = info.uuidTarget;
-            response.Mode = info.pose.Mode;
-
-            if (string.IsNullOrEmpty(subscribeToPoseRequest.WebhookUrl))
-            {
-                response.WebhookUrl = "";
-                response.WebsocketUrl = Request.Host.ToString();
-                // Notice: starting websocket server is done autom. by the client, when calling "URL:/ws"
+            WorldAnalysisConnections.Singleton.SubscribeToPose(info, parentUUID);
 
-                // todo: register the client, so the websocket will send to it pose updates
-            }
-            else
-            {
-                response.WebhookUrl = subscribeToPoseRequest.WebhookUrl;
-                response.WebsocketUrl = null;
-            }
             return new ObjectResult(response);
         }
 
@@ -174,15 +219,21 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers
         /// </summary>
         public override IActionResult UnsubscribeFromPose([FromRoute(Name = "subscriptionUUID")][Required] Guid subscriptionUUID, [FromHeader(Name = "token")] string token, [FromHeader(Name = "sessionID")] string sessionID)
         {
-            // todo: compare token and sessionID
+            if (!Startup.IsAccessGranted(token)) return StatusCode(511, new Error() { Message = "Invalid token!" });
+
+            // todo: compare sessionID
 
             // Remove the subscription from the list?
             if (m_subscriptionsPoses.ContainsKey(subscriptionUUID)) m_subscriptionsPoses.Remove(subscriptionUUID);
+            else
+            {
+                //return StatusCode(404, new Error() { Message = "Unsubscribe UUID not found!" });
+            }
 
             // Inform the module(s) that the subscription ended
-            WorldAnalysisModules.Singleton.UnsubscribeFromPose(subscriptionUUID);
+            WorldAnalysisConnections.Singleton.UnsubscribeFromPose(subscriptionUUID);
 
-            return StatusCode(200, "Ok!");
+            return StatusCode(200, new Success() { Message = "Unsubscription successfull." });
         }
 
         /// <summary>
@@ -190,7 +241,9 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers
         /// </summary>
         public override IActionResult UpdateSubscription([FromRoute(Name = "subscriptionUUID")][Required] Guid subscriptionUUID, [FromBody] UpdateSubscriptionRequest updateSubscriptionRequest, [FromHeader(Name = "token")] string token, [FromHeader(Name = "sessionID")] string sessionID)
         {
-            // todo: compare token and sessionID
+            if (!Startup.IsAccessGranted(token)) return StatusCode(511, new Error() { Message = "Invalid token!" });
+
+            // todo: compare sessionID
 
             // todo: inform the module(s) that the subscription changed
 
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 8a76568e404ccd1c8b622f84521d46a4453f5327..822931138c2f13ab348f117112b00f5c7fc3360e 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
@@ -43,11 +43,13 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers
     //
     public class WebSocketController : ControllerBase
     {
+        private WebSocket websocket;
+        static public int WebSocketControllerInstanceCount = 0;
+
         private string currentName = "";
         private bool registered = false;
         private bool firstTime = true;
         private int timeCnt = 3;
-        private WebSocket websockets;
 
         [HttpGet("/ws")]
         public async Task Get()
@@ -62,7 +64,8 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers
                 }
                 else if (webSocket.State == WebSocketState.Open)
                 {
-                    await HandleClientData(HttpContext, webSocket);
+                    // Go to the loop...
+                    await WebSocketServer_Loop(HttpContext, webSocket);
                 }
             }
             else
@@ -75,63 +78,36 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers
         //
         // Send a line of text
         //
-        private async Task SendText(WebSocket webSocket, string text)
+        static private async Task SendText(WebSocket ws, string msg)
         {
-            // Response an OK message
-            var message = text;
+            var message = msg;
             var bytes = Encoding.UTF8.GetBytes(message);
             var arraySegment = new ArraySegment<byte>(bytes, 0, bytes.Length);
-            await webSocket.SendAsync(arraySegment, WebSocketMessageType.Text, true, CancellationToken.None);
+            await ws.SendAsync(arraySegment, WebSocketMessageType.Text, true, CancellationToken.None);
         }
 
-        public void SendText(string text)
+        public void SendText(string msg)
         {
-            // Response an OK message
-            var message = text;
+            var message = msg;
             var bytes = Encoding.UTF8.GetBytes(message);
             var arraySegment = new ArraySegment<byte>(bytes, 0, bytes.Length);
-            websockets.SendAsync(arraySegment, WebSocketMessageType.Text, true, CancellationToken.None);
+            websocket.SendAsync(arraySegment, WebSocketMessageType.Text, true, CancellationToken.None);
         }
 
         //
-        // Send the time all seconds
+        // Send a demo pose all seconds
         //
-        //[HttpGet("/ws/time")]
-        private async Task SendTime(WebSocket webSocket)
-        {
-            while (true)
-            {
-                var message = "Time=" + DateTime.Now.ToLocalTime();
-
-                if (webSocket.State == WebSocketState.Open)
-                {
-                    timeCnt--;
-                    if (timeCnt < 0)
-                    {
-                        await SendText(webSocket, "TimeStop");
-                        break;
-                    }
-                    else await SendText(webSocket, message);
-                }
-                else if (webSocket.State == WebSocketState.Closed || webSocket.State == WebSocketState.Aborted)
-                {
-                    break;
-                }
-                Thread.Sleep(1000);
-            }
-        }
-
         float rotInc = 0;
-        private async Task SendDemoPose(WebSocket webSocket)
+        private async Task SendDemoPose(WebSocket ws)
         {
             while (true)
             {
-                if (webSocket.State == WebSocketState.Open)
+                if (ws.State == WebSocketState.Open)
                 {
                     timeCnt--;
                     if (timeCnt < 0)
                     {
-                        await SendText(webSocket, "PoseStop");
+                        await SendText(ws, "PoseStop");
                         break;
                     }
                     else
@@ -153,13 +129,13 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers
 
                         string json = pose.ToJson();
 
-                        await SendText(webSocket, "Pose=" + json);
+                        await SendText(ws, "NewPose=" + json);
                     }
                 }
-                else if (webSocket.State == WebSocketState.Closed || webSocket.State == WebSocketState.Aborted)
+                else if (ws.State == WebSocketState.Closed || ws.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);
+                    if (WorldAnalysisConnections.Singleton.modules.Contains(currentModule)) WorldAnalysisConnections.Singleton.modules.Remove(currentModule);
+                    if (WorldAnalysisConnections.Singleton.clients.Contains(currentClient)) WorldAnalysisConnections.Singleton.clients.Remove(currentClient);
                     currentClient = null;
                     currentModule = null;
                     break;
@@ -171,140 +147,196 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers
         private Module currentModule;
         private Client currentClient;
 
-        private async void OnReceiveText(WebSocket webSocket, string msg)
+        private async void OnReceiveText(string msg)
         {
+            #region Register the client/module
             if (firstTime)
             {
-                #region Register the client/module
-                if (msg.StartsWith("RegisterModule:"))
+                if (msg.StartsWith("RegisterModule="))
                 {
                     registered = true;
                     firstTime = false;
-                    currentName = msg.Split(':')[1];
+                    currentName = msg.Split('=')[1];
                     if (currentModule == null && currentClient == null)
                     {
                         currentModule = new Module();
                         currentModule.name = currentName;
                         currentModule.websockets = this;
-                        WorldAnalysisModules.Singleton.modules.Add(currentModule);
-                        await SendText(webSocket, "ARF World Analysis Server: You are now registered as a module: " + currentName);
+                        WorldAnalysisConnections.Singleton.modules.Add(currentModule);
+                        SendText($"ARF World Analysis Server: #{ WebSocketControllerInstanceCount } You are now registered as module: { currentName }");
                     }
                 }
-                else if (msg.StartsWith("RegisterClient:"))
+                else if (msg.StartsWith("RegisterClient="))
                 {
                     registered = true;
                     firstTime = false;
-                    currentName = msg.Split(':')[1];
+                    currentName = msg.Split('=')[1];
                     if (currentModule == null && currentClient == null)
                     {
                         currentClient = new Client();
                         currentClient.name = currentName;
                         currentClient.websockets = this;
-                        WorldAnalysisModules.Singleton.clients.Add(currentClient);
-                        await SendText(webSocket, "ARF World Analysis Server: You are now registered as a client: " + currentName);
+                        WorldAnalysisConnections.Singleton.clients.Add(currentClient);
+                        SendText($"ARF World Analysis Server: #{ WebSocketControllerInstanceCount } You are now registered as client: { currentName }");
                     }
                 }
                 else
                 {
                     registered = false;
-                    await SendText(webSocket, "ARF World Analysis Server: Cannot register " + msg);
+                    SendText("ARF World Analysis Server: Cannot register " + msg);
                 }
                 return;
-                #endregion
             }
+            #endregion
 
             if (registered)
             {
                 //
-                // Messages from Analysis modules
+                // Some admin stuffs
                 //
-                if (msg.StartsWith("PoseNew:"))
+                if (msg == "Idle")
                 {
-                    // todo: parse the json string
-
-                    // Send the pose to the client(s)
-                    Pose p = new Pose();
-                    WorldAnalysisModules.Singleton.SendPoseToClients(p);
-                    await SendText(webSocket, "RequestNextPose");
+                    SendText("Idle");
                 }
-                else if (msg.StartsWith("Capabilities of"))  // Receive capab. from a module
+                else if (msg == "Busy")
                 {
-                    // Client is sending its capabilities
-                    string[] str_cap = msg.Split('=');
-                    Capability _c = JsonConvert.DeserializeObject<Capability>(str_cap[1]);
-                    if (currentModule != null) currentModule.capabilities.Add(_c);
+                    SendText("Busy");
+                }
+                else if (msg.StartsWith("UnregisterModule="))
+                {
+                    string name = msg.Split('=')[1];
+
+                    // Unregister a client (e.g. Unity client)
+                    Module module = null;
+                    foreach (var item in WorldAnalysisConnections.Singleton.modules) if (item.name == name) module = item;
+                    if (module != null)
+                    {
+                        WorldAnalysisConnections.Singleton.modules.Remove(module);
+                        SendText("UnregisterModuleOK");
+                    }
+                    currentName = "";
+                    firstTime = true;
+                    registered = false;
                 }
+                else if (msg.StartsWith("UnregisterClient="))
+                {
+                    string name = msg.Split('=')[1];
 
+                    // Unregister a client (e.g. Unity client)
+                    Client client = null;
+                    foreach (var item in WorldAnalysisConnections.Singleton.clients) if (item.name == name) client = item;
+                    if (client != null)
+                    {
+                        WorldAnalysisConnections.Singleton.clients.Remove(client);
+                        SendText("UnregisterClientOK");
+                    }
+                    currentName = "";
+                    firstTime = true;
+                    registered = false;
+                }
                 //
-                // Messages from Unity clients
+                // OpenAPI
                 //
-                else if (msg.StartsWith("PoseStart")) // send some fake poses to Unity clients
+                else if (msg == "PoseIsNowSubscribed")
                 {
-                    await SendDemoPose(webSocket);
+                    SendText("RequestNextPose");
                 }
 
                 //
-                // Messages from modules and clients
+                // Messages from a module (Analysis)
                 //
-                else if (msg.StartsWith("TimeStart"))  // send time to modules/clients
+                else if (msg.StartsWith("Capabilities="))  // Receive capab. from a module
                 {
-                    if (msg.Contains(':')) timeCnt = int.Parse(msg.Split(':')[1]);
-                    else timeCnt = 3;
-                    await SendTime(webSocket);
+                    // Module is sending their capabilities
+                    string[] str_cap = msg.Split('=');
+                    Capability _c = JsonConvert.DeserializeObject<Capability>(str_cap[1]);
+                    if (currentModule != null) currentModule.capabilities.Add(_c);
                 }
-                else if (msg == "UnregisterClient")
+                else if (msg.StartsWith("NewPose="))
                 {
-                    // Unregister a client (e.g. Unity client)
-                    currentName = "";
-                    firstTime = true;
-                    registered = false;
-                    await SendText(webSocket, "SessionStop");
+                    string[] str_pose = msg.Split('=');
+
+                    // Send the pose to the client(s)
+                    Pose pose = JsonConvert.DeserializeObject<Pose>(str_pose[1]);
+
+                    //WorldAnalysisConnections.Singleton.SendPoseToClients(pose);
+                    WorldAnalysisConnections.Singleton.SendPoseToClients(str_pose[1]);
+
+                    // todo: if there are some subscription ask modules for new pose
+                    SendText("RequestNextPose");
                 }
-                else if (msg == "PoseIsRegistered")
+                else if (msg.StartsWith("Error="))
                 {
-                    await SendText(webSocket, "RequestNextPose");
+                    string errorMsg = msg.Split('=')[1];
+                    foreach (var item in WorldAnalysisConnections.Singleton.clients)
+                    {
+                        await SendText(item.websockets.websocket, errorMsg);
+                    }
                 }
-                else if (msg == "Idle")
+
+                //
+                // Messages from a client (Unity)
+                //
+                else if (msg.StartsWith("PoseStart")) // send some fake poses to Unity clients
                 {
-                    await SendText(webSocket, "Idle");
+                    await SendDemoPose(websocket);
                 }
-                else if (msg == "Busy")
+                else if (msg.StartsWith("CurrentUserPose="))
                 {
-                    await SendText(webSocket, "Busy");
+                    // A client (Unity) is sending the current user posistion
+
+                    // Send new user pose to all modules
+                    foreach (var item in WorldAnalysisConnections.Singleton.modules)
+                    {
+                        await SendText(item.websockets.websocket, msg);
+                    }
+
+                    //// Test: send user pose back to clients
+                    //string[] str_pose = msg.Split('=');
+                    //Pose pose = JsonConvert.DeserializeObject<Pose>(str_pose[1]);
+                    //pose.Value.Position[2] += 1f;
+                    //WorldAnalysisConnections.Singleton.SendPoseToClients(pose);
                 }
+
+                //
+                // Messages from modules and clients
+                //
                 else
                 {
                     // Send a response
-                    await SendText(webSocket, "ARF World Analysis Server: I got this unknown message: " + msg);
+                    SendText("ARF World Analysis Server: I got this unknown message: " + msg);
                 }
             }
         }
 
-        private async Task HandleClientData(HttpContext context, WebSocket webSocket)
+        private async Task WebSocketServer_Loop(HttpContext context, WebSocket ws)
         {
+            websocket = ws;
+            WebSocketControllerInstanceCount++;
+
             var buffer = new byte[1024 * 4];
-            websockets = webSocket;
 
             // Read/get the first data block
-            WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
+            WebSocketReceiveResult result = await ws.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
             if (result.MessageType == WebSocketMessageType.Text)
             {
                 string getMsg = System.Text.Encoding.UTF8.GetString(buffer, 0, result.Count);
-                OnReceiveText(webSocket, getMsg);
+                OnReceiveText(getMsg);
             }
 
             // Entering the loop
             while (!result.CloseStatus.HasValue)
             {
                 // Read/get the next block
-                result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
+                result = await ws.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
                 if (result.MessageType == WebSocketMessageType.Text)
                 {
                     string getMsg = System.Text.Encoding.UTF8.GetString(buffer, 0, result.Count);
-                    OnReceiveText(webSocket, getMsg);
+                    OnReceiveText(getMsg);
                 }
             }
-            await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
+            await ws.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
+            WebSocketControllerInstanceCount--;
         }
 
 
diff --git a/server/worldanalysis/src/ETSI.ARF.OpenAPI.WorldAnalysis/ETSI-ARF/WorldAnalysisModules.cs b/server/worldanalysis/src/ETSI.ARF.OpenAPI.WorldAnalysis/ETSI-ARF/WorldAnalysisConnections.cs
similarity index 57%
rename from server/worldanalysis/src/ETSI.ARF.OpenAPI.WorldAnalysis/ETSI-ARF/WorldAnalysisModules.cs
rename to server/worldanalysis/src/ETSI.ARF.OpenAPI.WorldAnalysis/ETSI-ARF/WorldAnalysisConnections.cs
index 6ec1f5606f492ecc484ee591cd3e9d252d6b64ef..c864547b3750de69a96ae41035c7a6f3c4788622 100644
--- a/server/worldanalysis/src/ETSI.ARF.OpenAPI.WorldAnalysis/ETSI-ARF/WorldAnalysisModules.cs
+++ b/server/worldanalysis/src/ETSI.ARF.OpenAPI.WorldAnalysis/ETSI-ARF/WorldAnalysisConnections.cs
@@ -17,20 +17,21 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis
         public WebSocketController websockets;
     }
 
-    // For management of WA clinet (e.g. Unity client)
+    // For management of WA client (e.g. Unity client)
     public class Client
     {
         public string name;
         public string session;
+        public VectorQuaternionPoseValue currentUserPose;
         public WebSocketController websockets;
     }
 
-    public class WorldAnalysisModules
+    public class WorldAnalysisConnections
     {
-        static public WorldAnalysisModules Singleton = new WorldAnalysisModules();
+        static public WorldAnalysisConnections Singleton = new WorldAnalysisConnections();
 
         public List<Module> modules = new List<Module>();
-        public List<Client> clients = new List<Client>();
+        public List<Client> clients = new List<Client>();   // e.g. Unity clients
 
         // todo
         // Manage the sessions and modules
@@ -58,13 +59,24 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis
             return list;
         }
 
-        public void ConfigureFramerate(PoseConfiguration poseConfiguration)
+        public bool ConfigureFramerate(PoseConfiguration poseConfiguration)
         {
-            foreach (var item in modules)
+            bool ok = false;
+            foreach (var m in modules)
             {
-                // todo: configure the module via websocket
-                item.websockets.SendText("ConfigureFramerate:" + poseConfiguration.ToJson());
+                bool moduleHasCap = false;
+                foreach (var c in m.capabilities)
+                {
+                    if ((int)poseConfiguration.TrackableType == (int)c.TrackableType)
+                    {
+                        moduleHasCap = true;
+                        break;
+                    }
+                }
+                // Configure the module via websocket
+                if (moduleHasCap) m.websockets.SendText("ConfigureFramerate=" + poseConfiguration.ToJson());
             }
+            return ok;
         }
 
         public Pose GetPose(Guid trackableOrAnchorUUID, ModeWorldAnalysis mode)
@@ -73,39 +85,48 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis
             foreach (var item in modules)
             {
                 // todo: get the pose via websocket
-                item.websockets.SendText("GetPose:" + trackableOrAnchorUUID + ":" + mode.ToString());
+                item.websockets.SendText("GetPose=" + trackableOrAnchorUUID + "=" + mode.ToString());
 
                 // todo: find the pose with the best confidence?
                 // How to get the results !?!?! (List with results, per Modules)
             }
             return result;
         }
-
-
-        public void SubscribeToPose(SubscriptionInfo info)
+        
+        public void SubscribeToPose(SubscriptionInfo info, Guid parentTrackableUUID)
         {
             // Send to all modules a request of subscription
             foreach (var item in modules)
             {
-                item.websockets.SendText("SubscribePose:" + info.uuidTarget.ToString());
+                if (parentTrackableUUID == Guid.Empty) item.websockets.SendText("SubscribePose=" + info.uuidSub + "=" + info.subscription.ToJson());
+                else item.websockets.SendText("SubscribeSimulatedPose=" + info.uuidSub + "=" + info.subscription.ToJson() + "=" + parentTrackableUUID.ToString());
             }
         }
 
-        public void UnsubscribeFromPose(Guid uuid)
+        public void UnsubscribeFromPose(Guid subscriptionUUID)
         {
             // Send to all modules a request of subscription
             foreach (var item in modules)
             {
-                item.websockets.SendText("UnsubscribePose:" + uuid.ToString());
+                item.websockets.SendText("UnsubscribePose=" + subscriptionUUID.ToString());
+            }
+        }
+
+        public void SendPoseToClients(Pose pose)
+        {
+            // Send to all clients with valid subscription the new pose
+            foreach (var item in clients)
+            {
+                item.websockets.SendText("NewPose=" + pose.ToJson());
             }
         }
 
-        public void SendPoseToClients(Pose p)
+        public void SendPoseToClients(string str_pose)
         {
             // Send to all clients with valid subscription the new pose
             foreach (var item in clients)
             {
-                item.websockets.SendText("Pose=" + p.ToJson());
+                item.websockets.SendText("NewPose=" + str_pose);
             }
         }
     }
diff --git a/server/worldanalysis/src/ETSI.ARF.OpenAPI.WorldAnalysis/Startup.cs b/server/worldanalysis/src/ETSI.ARF.OpenAPI.WorldAnalysis/Startup.cs
index f56fad2d4b07afcd683ccc65a18b464cac76890b..2a3f67c8c81faf23840f8f5e81c90a997d5cb9ba 100644
--- a/server/worldanalysis/src/ETSI.ARF.OpenAPI.WorldAnalysis/Startup.cs
+++ b/server/worldanalysis/src/ETSI.ARF.OpenAPI.WorldAnalysis/Startup.cs
@@ -15,7 +15,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 //
-// Last change: June 2024
+// Last change: September 2024
 //
 
 /*
@@ -23,7 +23,7 @@
  *
  * API ensuring interoperability between Scene Management and a World Analysis service
  *
- * The version of the OpenAPI document: 2.0.1
+ * The version of the OpenAPI document: 2.0.2
  * 
  * Generated by: https://openapi-generator.tech
  */
@@ -64,17 +64,18 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis
         /// <summary>
         /// The API version. (how to read it from the yaml?)
         /// </summary>
-        static public string apiVersion = "2.0.1";
+        static public string apiVersion = "2.0.0";
 
         /// <summary>
         /// Demo access key
         /// </summary>
-        static public string accessKey = "My!Key.ETSI";
+        static public string accessKey = "ARF";
 
         /// <summary>
         /// Demo secret key
         /// </summary>
-        static public string secretKey = "GW0Wae1t4Cs5rAqEbPYFWO9J5nSbpJXxp1F3uv0J";
+        //static public string secretKey = "GW0Wae1t4Cs5rAqEbPYFWO9J5nSbpJXxp1F3uv0J";
+        static public string secretKey = "hhi";
 
         /// <summary>
         /// Constructor
@@ -90,6 +91,20 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis
         /// </summary>
         public IConfiguration Configuration { get; }
 
+        /// <summary>
+        /// SylR: Check if the request is authorized
+        /// </summary>
+        /// <param name="token"></param>
+        /// <returns></returns>
+        static public bool IsAccessGranted(string token)
+        {
+            if (token == null) return false;
+            else if (token == "dev") return true;   // developermode
+
+            string[] t = token.Split('&');
+            return t[0] == accessKey && t[1] == secretKey;
+        }
+
         /// <summary>
         /// This method gets called by the runtime. Use this method to add services to the container.
         /// </summary>
@@ -116,7 +131,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis
                 {
                     c.EnableAnnotations(enableAnnotationsForInheritance: true, enableAnnotationsForPolymorphism: true);
                     
-                    c.SwaggerDoc("2.0.1", new OpenApiInfo
+                    c.SwaggerDoc(apiVersion, new OpenApiInfo
                     {
                         Title = "World Analysis API",
                         Description = "World Analysis API (ASP.NET Core 5.0)",
@@ -132,7 +147,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis
                             Name = "NoLicense",
                             Url = new Uri("https://opensource.org/licenses/BSD-3-Clause")
                         },
-                        Version = "2.0.1",
+                        Version = apiVersion,
                     });
                     c.CustomSchemaIds(type => type.FriendlyId(true));
                     c.IncludeXmlComments($"{AppContext.BaseDirectory}{Path.DirectorySeparatorChar}{Assembly.GetEntryAssembly().GetName().Name}.xml");
@@ -183,7 +198,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis
                     // set route prefix to openapi, e.g. http://localhost:8080/openapi/index.html
                     c.RoutePrefix = "openapi";
                     //TODO: Either use the SwaggerGen generated OpenAPI contract (generated from C# classes)
-                    c.SwaggerEndpoint("/openapi/2.0.1/openapi.json", "World Analysis API");
+                    c.SwaggerEndpoint("/openapi/" + apiVersion  + "/openapi.json", "World Analysis API");
 
                     //TODO: Or alternatively use the original OpenAPI contract that's included in the static files
                     // c.SwaggerEndpoint("/openapi-original.json", "World Analysis API Original");