Skip to content
Snippets Groups Projects
Commit afbfe86d authored by Sylvain Renault's avatar Sylvain Renault
Browse files

Implementation of the new API (generator issues)

parent 13f4319d
No related branches found
No related tags found
2 merge requests!2Some trst implementation for REST.,!1Some trst implementation for REST.
openapi @ b639a021
Subproject commit 073fd7213fd9e6ebc2f8a47d628a650de30c8bc4 Subproject commit b639a02180c2b5e301c77483b3a2fa645ba94169
...@@ -41,39 +41,52 @@ using ETSI.ARF.OpenAPI.WorldAnalysis.Attributes; ...@@ -41,39 +41,52 @@ using ETSI.ARF.OpenAPI.WorldAnalysis.Attributes;
using ETSI.ARF.OpenAPI.WorldAnalysis.Models; using ETSI.ARF.OpenAPI.WorldAnalysis.Models;
namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers
{ {
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
[ApiController] [ApiController]
public class PoseApiControlleImpl : PoseApiController public class PoseApiControlleImpl : PoseApiController
{ {
/// <summary> /// <summary>
/// Specify the a minimum frame rate for pose estimation for Trackable types /// Specify the a minimum frame rate for pose estimation for Trackable types
/// </summary> /// </summary>
public override IActionResult ConfigureFramerate([FromBody]PoseConfiguration poseConfiguration, [FromHeader (Name = "token")]string token, [FromHeader (Name = "sessionID")]string sessionID) public override IActionResult ConfigureFramerate([FromBody] PoseConfiguration poseConfiguration, [FromHeader(Name = "token")] string token, [FromHeader(Name = "sessionID")] string sessionID)
{ {
// todo: compare token and sessionID // todo: compare token and sessionID
return StatusCode(405, "Not supported yet!"); // Notify the modules that the client need a new framerate
WorldAnalysisModules.Singleton.ConfigureFramerate(poseConfiguration);
return StatusCode(200, "Ok.");
} }
/// <summary> /// <summary>
/// Request the last pose of a single Anchor or Trackable /// Request the last pose of a single Anchor or Trackable
/// </summary> /// </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) 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 // todo: compare token and sessionID
return StatusCode(405, "Not supported yet!"); // Request from the modules a new pose of a single UUID
Pose result;
result = WorldAnalysisModules.Singleton.GetPose(trackableOrAnchorUUID, mode);
return new ObjectResult(result);
} }
/// <summary> /// <summary>
/// Request the last pose of a batch of Anchor or Trackable /// Request the last pose of a batch of Anchor or Trackable
/// </summary> /// </summary>
public override IActionResult GetPoses([FromQuery (Name = "uuid")][Required()]List<GetPosesUuidParameterInner> uuid, [FromHeader (Name = "token")]string token, [FromHeader (Name = "sessionID")]string sessionID) public override IActionResult GetPoses([FromQuery(Name = "uuid")][Required()] List<UuidAndMode> uuid, [FromHeader(Name = "token")] string token, [FromHeader(Name = "sessionID")] string sessionID)
{ {
return StatusCode(405, "Not supported yet!"); // todo: compare token and 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));
}
return new ObjectResult(result);
} }
#pragma warning disable CS1591 // Fehlendes XML-Kommentar fr ffentlich sichtbaren Typ oder Element #pragma warning disable CS1591 // Fehlendes XML-Kommentar fr ffentlich sichtbaren Typ oder Element
...@@ -99,42 +112,53 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers ...@@ -99,42 +112,53 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers
/// <summary> /// <summary>
/// Get information about a subscription /// Get information about a subscription
/// </summary> /// </summary>
public override IActionResult GetSubscription([FromRoute (Name = "subscriptionUUID")][Required]Guid subscriptionUUID, [FromHeader (Name = "token")]string token, [FromHeader (Name = "sessionID")]string sessionID) 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 // todo: compare token and sessionID
// todo: search for a subscription and send it back
return StatusCode(405, "Not supported yet!"); return StatusCode(405, "Not supported yet!");
} }
/// <summary> /// <summary>
/// Subscribe to collect the pose of an AR device, an Anchor or a Trackable /// Subscribe to collect the pose of an AR device, an Anchor or a Trackable
/// </summary> /// </summary>
public override IActionResult SubscribeToPose([FromBody]SubscribeToPoseRequest subscribeToPoseRequest, [FromHeader (Name = "token")]string token, [FromHeader (Name = "sessionID")]string sessionID) public override IActionResult SubscribeToPose([FromBody] SubscribeToPoseRequest subscribeToPoseRequest, [FromHeader(Name = "token")] string token, [FromHeader(Name = "sessionID")] string sessionID)
{ {
// todo: compare token and sessionID // todo: compare token and sessionID
int validity = subscribeToPoseRequest.Validity; // todo: is to handle here or by the client? int validity = subscribeToPoseRequest.Validity; // todo: is to handle here or by the client?
// We add the subscription // We add the subscription
SubscriptionInfo sub = new SubscriptionInfo(); SubscriptionInfo info = new SubscriptionInfo();
sub.uuid = new Guid(); info.uuid = new Guid();
sub.timeValidity = DateTime.Now.AddMilliseconds(validity / 1000.0f); info.uuidTarget = subscribeToPoseRequest.Target;
sub.pose = new Pose(); info.timeValidity = DateTime.Now.AddMilliseconds(validity / 1000.0f);
sub.pose.Mode = subscribeToPoseRequest.Mode[0]; info.pose = new Pose();
sub.uuidTarget = subscribeToPoseRequest.Target; info.pose.Mode = subscribeToPoseRequest.Mode;
m_subscriptionsPoses.Add(sub.uuid, sub); m_subscriptionsPoses.Add(info.uuid, info);
// todo: handle multiple subscriptions ?
// subscribeToPoseRequest.Targets[]
// subscribeToPoseRequest.Modes[]
// 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(); SubscribeToPose200Response response = new SubscribeToPose200Response();
response.Uuid = sub.uuid;
response.Validity = validity; response.Validity = validity;
response.Target = sub.uuidTarget; response.Uuid = info.uuid;
response.Mode = sub.pose.Mode; response.Target = info.uuidTarget;
response.Mode = info.pose.Mode;
if (string.IsNullOrEmpty(subscribeToPoseRequest.WebhookUrl)) if (string.IsNullOrEmpty(subscribeToPoseRequest.WebhookUrl))
{ {
response.WebhookUrl = ""; response.WebhookUrl = "";
response.WebsocketUrl = Request.Host.ToString(); response.WebsocketUrl = Request.Host.ToString();
// Notice: starting websocket server is done autom. by the client, when calling "URL:/ws" // Notice: starting websocket server is done autom. by the client, when calling "URL:/ws"
// todo: register the client, so the websocket will send to it pose updates // todo: register the client, so the websocket will send to it pose updates
} }
else else
...@@ -143,26 +167,33 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers ...@@ -143,26 +167,33 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers
response.WebsocketUrl = null; response.WebsocketUrl = null;
} }
return new ObjectResult(response); return new ObjectResult(response);
//return StatusCode(405, "Not supported yet!");
} }
/// <summary> /// <summary>
/// Remove a subscription to a given pose /// Remove a subscription to a given pose
/// </summary> /// </summary>
public override IActionResult UnsubscribeFromPose([FromRoute (Name = "subscriptionUUID")][Required]Guid subscriptionUUID, [FromHeader (Name = "token")]string token, [FromHeader (Name = "sessionID")]string sessionID) 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 // todo: compare token and sessionID
return StatusCode(405, "Not supported yet!"); // Remove the subscription from the list?
if (m_subscriptionsPoses.ContainsKey(subscriptionUUID)) m_subscriptionsPoses.Remove(subscriptionUUID);
// Inform the module(s) that the subscription ended
WorldAnalysisModules.Singleton.UnsubscribeFromPose(subscriptionUUID);
return StatusCode(200, "Ok!");
} }
/// <summary> /// <summary>
/// Update a subscription /// Update a subscription
/// </summary> /// </summary>
public override IActionResult UpdateSubscription([FromRoute (Name = "subscriptionUUID")][Required]Guid subscriptionUUID, [FromBody]UpdateSubscriptionRequest updateSubscriptionRequest, [FromHeader (Name = "token")]string token, [FromHeader (Name = "sessionID")]string sessionID) 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 // todo: compare token and sessionID
// todo: inform the module(s) that the subscription changed
return StatusCode(405, "Not supported yet!"); return StatusCode(405, "Not supported yet!");
} }
} }
......
...@@ -47,6 +47,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers ...@@ -47,6 +47,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers
private bool registered = false; private bool registered = false;
private bool firstTime = true; private bool firstTime = true;
private int timeCnt = 3; private int timeCnt = 3;
private WebSocket websockets;
[HttpGet("/ws")] [HttpGet("/ws")]
public async Task Get() public async Task Get()
...@@ -83,6 +84,15 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers ...@@ -83,6 +84,15 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers
await webSocket.SendAsync(arraySegment, WebSocketMessageType.Text, true, CancellationToken.None); await webSocket.SendAsync(arraySegment, WebSocketMessageType.Text, true, CancellationToken.None);
} }
public void SendText(string text)
{
// Response an OK message
var message = text;
var bytes = Encoding.UTF8.GetBytes(message);
var arraySegment = new ArraySegment<byte>(bytes, 0, bytes.Length);
websockets.SendAsync(arraySegment, WebSocketMessageType.Text, true, CancellationToken.None);
}
// //
// Send the time all seconds // Send the time all seconds
// //
...@@ -91,7 +101,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers ...@@ -91,7 +101,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers
{ {
while (true) while (true)
{ {
var message = "ARF World Analysis Server, Time = " + DateTime.Now.ToLocalTime(); var message = "Time=" + DateTime.Now.ToLocalTime();
if (webSocket.State == WebSocketState.Open) if (webSocket.State == WebSocketState.Open)
{ {
...@@ -112,7 +122,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers ...@@ -112,7 +122,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers
} }
float rotInc = 0; float rotInc = 0;
private async Task SendPose(WebSocket webSocket) private async Task SendDemoPose(WebSocket webSocket)
{ {
while (true) while (true)
{ {
...@@ -143,7 +153,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers ...@@ -143,7 +153,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers
string json = pose.ToJson(); string json = pose.ToJson();
await SendText(webSocket, json); await SendText(webSocket, "Pose=" + json);
} }
} }
else if (webSocket.State == WebSocketState.Closed || webSocket.State == WebSocketState.Aborted) else if (webSocket.State == WebSocketState.Closed || webSocket.State == WebSocketState.Aborted)
...@@ -165,7 +175,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers ...@@ -165,7 +175,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers
{ {
if (firstTime) if (firstTime)
{ {
// Register the client/module #region Register the client/module
if (msg.StartsWith("RegisterModule:")) if (msg.StartsWith("RegisterModule:"))
{ {
registered = true; registered = true;
...@@ -175,6 +185,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers ...@@ -175,6 +185,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers
{ {
currentModule = new Module(); currentModule = new Module();
currentModule.name = currentName; currentModule.name = currentName;
currentModule.websockets = this;
WorldAnalysisModules.Singleton.modules.Add(currentModule); WorldAnalysisModules.Singleton.modules.Add(currentModule);
await SendText(webSocket, "ARF World Analysis Server: You are now registered as a module: " + currentName); await SendText(webSocket, "ARF World Analysis Server: You are now registered as a module: " + currentName);
} }
...@@ -188,6 +199,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers ...@@ -188,6 +199,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers
{ {
currentClient = new Client(); currentClient = new Client();
currentClient.name = currentName; currentClient.name = currentName;
currentClient.websockets = this;
WorldAnalysisModules.Singleton.clients.Add(currentClient); WorldAnalysisModules.Singleton.clients.Add(currentClient);
await SendText(webSocket, "ARF World Analysis Server: You are now registered as a client: " + currentName); await SendText(webSocket, "ARF World Analysis Server: You are now registered as a client: " + currentName);
} }
...@@ -197,36 +209,61 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers ...@@ -197,36 +209,61 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers
registered = false; registered = false;
await SendText(webSocket, "ARF World Analysis Server: Cannot register " + msg); await SendText(webSocket, "ARF World Analysis Server: Cannot register " + msg);
} }
return;
#endregion
} }
else if (registered)
if (registered)
{ {
if (msg.StartsWith("PoseStart")) //
// Messages from Analysis modules
//
if (msg.StartsWith("PoseNew:"))
{ {
if (msg.Contains(':')) timeCnt = int.Parse(msg.Split(':')[1]); // todo: parse the json string
else timeCnt = 3;
await SendPose(webSocket); // Send the pose to the client(s)
} Pose p = new Pose();
else if (msg.StartsWith("TimeStart")) WorldAnalysisModules.Singleton.SendPoseToClients(p);
{ await SendText(webSocket, "RequestNextPose");
if (msg.Contains(':')) timeCnt = int.Parse(msg.Split(':')[1]);
else timeCnt = 3;
await SendTime(webSocket);
} }
else if (msg.StartsWith("Capabilities")) else if (msg.StartsWith("Capabilities of")) // Receive capab. from a module
{ {
// Client is sending its capabilities // Client is sending its capabilities
string[] str_cap = msg.Split('='); string[] str_cap = msg.Split('=');
Capability _c = JsonConvert.DeserializeObject<Capability>(str_cap[1]); Capability _c = JsonConvert.DeserializeObject<Capability>(str_cap[1]);
if (currentModule != null) currentModule.capabilities.Add(_c); if (currentModule != null) currentModule.capabilities.Add(_c);
} }
//
// Messages from Unity clients
//
else if (msg.StartsWith("PoseStart")) // send some fake poses to Unity clients
{
await SendDemoPose(webSocket);
}
//
// Messages from modules and clients
//
else if (msg.StartsWith("TimeStart")) // send time to modules/clients
{
if (msg.Contains(':')) timeCnt = int.Parse(msg.Split(':')[1]);
else timeCnt = 3;
await SendTime(webSocket);
}
else if (msg == "UnregisterClient") else if (msg == "UnregisterClient")
{ {
// Unregister client/user // Unregister a client (e.g. Unity client)
currentName = ""; currentName = "";
firstTime = true; firstTime = true;
registered = false; registered = false;
await SendText(webSocket, "SessionStop"); await SendText(webSocket, "SessionStop");
} }
else if (msg == "PoseIsRegistered")
{
await SendText(webSocket, "RequestNextPose");
}
else if (msg == "Idle") else if (msg == "Idle")
{ {
await SendText(webSocket, "Idle"); await SendText(webSocket, "Idle");
...@@ -246,6 +283,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers ...@@ -246,6 +283,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis.Controllers
private async Task HandleClientData(HttpContext context, WebSocket webSocket) private async Task HandleClientData(HttpContext context, WebSocket webSocket)
{ {
var buffer = new byte[1024 * 4]; var buffer = new byte[1024 * 4];
websockets = webSocket;
// Read/get the first data block // Read/get the first data block
WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None); WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
......
...@@ -3,6 +3,8 @@ using System; ...@@ -3,6 +3,8 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using static ETSI.ARF.OpenAPI.WorldAnalysis.Controllers.PoseApiControlleImpl;
using ETSI.ARF.OpenAPI.WorldAnalysis.Controllers;
#pragma warning disable CS1591 // Fehlendes XML-Kommentar für öffentlich sichtbaren Typ oder Element #pragma warning disable CS1591 // Fehlendes XML-Kommentar für öffentlich sichtbaren Typ oder Element
namespace ETSI.ARF.OpenAPI.WorldAnalysis namespace ETSI.ARF.OpenAPI.WorldAnalysis
...@@ -12,6 +14,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis ...@@ -12,6 +14,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis
{ {
public string name; public string name;
public List<Capability> capabilities = new List<Capability>(); public List<Capability> capabilities = new List<Capability>();
public WebSocketController websockets;
} }
// For management of WA clinet (e.g. Unity client) // For management of WA clinet (e.g. Unity client)
...@@ -19,7 +22,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis ...@@ -19,7 +22,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis
{ {
public string name; public string name;
public string session; public string session;
public WebSocketController websockets;
} }
public class WorldAnalysisModules public class WorldAnalysisModules
...@@ -48,12 +51,63 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis ...@@ -48,12 +51,63 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis
foreach (var item in modules) foreach (var item in modules)
{ {
// todo: Check if uuid has the capability? // todo: Check if uuid has the capability?
// Get the world object from the storage via the module? // Get the world object from the world storage via the module?
// Use GetRelocalisation() ?
list.AddRange(item.capabilities); list.AddRange(item.capabilities);
} }
return list; return list;
} }
public void ConfigureFramerate(PoseConfiguration poseConfiguration)
{
foreach (var item in modules)
{
// todo: configure the module via websocket
item.websockets.SendText("ConfigureFramerate:" + poseConfiguration.ToJson());
}
}
public Pose GetPose(Guid trackableOrAnchorUUID, ModeWorldAnalysis mode)
{
Pose result = new Pose();
foreach (var item in modules)
{
// todo: get the pose via websocket
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)
{
// Send to all modules a request of subscription
foreach (var item in modules)
{
item.websockets.SendText("SubscribePose:" + info.uuidTarget.ToString());
}
}
public void UnsubscribeFromPose(Guid uuid)
{
// Send to all modules a request of subscription
foreach (var item in modules)
{
item.websockets.SendText("UnsubscribePose:" + uuid.ToString());
}
}
public void SendPoseToClients(Pose p)
{
// Send to all clients with valid subscription the new pose
foreach (var item in clients)
{
item.websockets.SendText("Pose=" + p.ToJson());
}
}
} }
} }
#pragma warning restore CS1591 // Fehlendes XML-Kommentar für öffentlich sichtbaren Typ oder Element #pragma warning restore CS1591 // Fehlendes XML-Kommentar für öffentlich sichtbaren Typ oder Element
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment