diff --git a/Editor/Scripts/WorldAnalysisInfoEditor.cs b/Editor/Scripts/WorldAnalysisInfoEditor.cs new file mode 100644 index 0000000000000000000000000000000000000000..70a489e197ac199bf1b5d640c030887df5254532 --- /dev/null +++ b/Editor/Scripts/WorldAnalysisInfoEditor.cs @@ -0,0 +1,39 @@ +// +// ARF - Augmented Reality Framework (ETSI ISG ARF) +// +// Copyright 2024 ETSI +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Last change: August 2024 +// + +using UnityEditor; + +[CustomEditor(typeof(WorldAnalysisInfo))] +public class WorldAnalysisInfoEditor : Editor +{ + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + + EditorGUILayout.Space(); + WorldAnalysisInfo srv = (WorldAnalysisInfo)target; + + string state = "";// srv.GetServerState(); + EditorGUILayout.LabelField("Server State", state); + + string api = "";// srv.GetAPIVersion(); + EditorGUILayout.LabelField("OpenAPI Version", api); + } +} diff --git a/Editor/Scripts/WorldAnalysisInfoEditor.cs.meta b/Editor/Scripts/WorldAnalysisInfoEditor.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..0642c98c929f8cb55c470c3ee423dafb38e19feb --- /dev/null +++ b/Editor/Scripts/WorldAnalysisInfoEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4b890e537ebae974b862e97bfefa51ad +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Scripts/WorldAnalysisServerEditor.cs b/Editor/Scripts/WorldAnalysisServerEditor.cs new file mode 100644 index 0000000000000000000000000000000000000000..4fe96c9164fa2618950d512348af3c6689c2552b --- /dev/null +++ b/Editor/Scripts/WorldAnalysisServerEditor.cs @@ -0,0 +1,174 @@ +// +// ARF - Augmented Reality Framework (ETSI ISG ARF) +// +// Copyright 2024 ETSI +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Last change: July 2024 +// + +using System.Collections; +using UnityEngine; +using UnityEditor; + +using ETSI.ARF.OpenAPI; +using ETSI.ARF.OpenAPI.WorldAnalysis; +using ETSI.ARF.WorldAnalysis; +using ETSI.ARF.WorldAnalysis.REST; + +[CustomEditor(typeof(WorldAnalysisServer))] +public class WorldStorageServerEditor : Editor +{ + WorldAnalysisServer server; + + private string state = ""; + private string version = ""; + + private string test = ""; + + private Queue handleResponseQueue = new Queue(); + + private ResponseObject pendingTest = null; + private ResponseObject pendingState = null; + private ResponseObject pendingVersion = null; + + public void OnEnable() + { + server = (WorldAnalysisServer)target; + } + + public override void OnInspectorGUI() + { + serializedObject.Update(); + + DrawDefaultInspector(); + EditorGUILayout.Space(); + + if (GUILayout.Button("Test server")) + { + TestPing(); + } + EditorGUILayout.LabelField("Test Response", test); + + EditorGUILayout.Space(); + + if (GUILayout.Button("Query server")) + { + QueryServer(); + } + + EditorGUILayout.LabelField("Server State", state); + EditorGUILayout.LabelField("OpenAPI Version", version); + + if (handleResponseQueue.Count > 0) + { + object o = handleResponseQueue.Dequeue(); + if (o.Equals(pendingTest)) + { + ResponseObject response = o as ResponseObject; + Debug.Log($"Get '{response.result}' from server"); + + test = response.result; + pendingTest = null; + EditorUtility.SetDirty(target); + } + else if (o.Equals(pendingState)) + { + ResponseObject response = o as ResponseObject; + Debug.Log($"Get '{response.result}' from server"); + + state = response.result; + pendingState = null; + EditorUtility.SetDirty(target); + } + else if (o.Equals(pendingVersion)) + { + ResponseObject response = o as ResponseObject; + Debug.Log($"Get '{response.result}' from server"); + + version = response.result; + pendingVersion = null; + EditorUtility.SetDirty(target); + } + else + { + Debug.Log("Unsupported response!"); + } + } + } + + public override bool RequiresConstantRepaint() + { + return handleResponseQueue.Count > 0; + } + + void OnSceneGUI() + { + Debug.Log("OnSceneGUI"); + } + + private void TestPing() + { + test = ""; + EditorUtility.SetDirty(target); + + if (server == null) + { + Debug.LogError("No server defined!"); + return; + } + + //string response = AdminRequest.PingSync(server); + //EditorUtility.DisplayDialog("Test Server", $"Get '{response}' from server", "OK"); + + if (pendingTest != null) + { + pendingTest.Cancel(); + } + + pendingTest = AdminRequest.PingAsync(server, (response) => + { + handleResponseQueue.Enqueue(response); + Debug.Log($"Request Time: { response.requestTime.ToLongTimeString() } / Total Time: { response.DeltaTime.TotalMilliseconds }ms\n\nContent:\n{ response.result }"); + }); + + Debug.Log("Starting request @ time: " + pendingTest.requestTime.ToLongTimeString() + "..."); + } + + private void QueryServer() + { + version = ""; + state = ""; + + if (pendingState != null) + { + pendingState.Cancel(); + } + + pendingState = AdminRequest.AdminAsync(server, (response) => + { + handleResponseQueue.Enqueue(response); + }); + + if (pendingVersion != null) + { + pendingVersion.Cancel(); + } + + pendingVersion = AdminRequest.VersionAsync(server, (response) => + { + handleResponseQueue.Enqueue(response); + }); + } +} \ No newline at end of file diff --git a/Editor/Scripts/WorldAnalysisServerEditor.cs.meta b/Editor/Scripts/WorldAnalysisServerEditor.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..b6c4ebcebcfe89fdf3913ab820a589eda451a592 --- /dev/null +++ b/Editor/Scripts/WorldAnalysisServerEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9899978f4c750de4b98f81a9c6937a94 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Scripts/WorldAnalysisUserEditor.cs b/Editor/Scripts/WorldAnalysisUserEditor.cs new file mode 100644 index 0000000000000000000000000000000000000000..043379e03f8193e15c2564926cecb02d3f798529 --- /dev/null +++ b/Editor/Scripts/WorldAnalysisUserEditor.cs @@ -0,0 +1,51 @@ +// +// ARF - Augmented Reality Framework (ETSI ISG ARF) +// +// Copyright 2022 ETSI +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Last change: June 2022 +// + +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; + +using ETSI.ARF.WorldAnalysis; + +[CustomEditor(typeof(WorldAnalysisUser))] +public class WorldStorageUserEditor : Editor +{ + WorldAnalysisUser user; + + public void OnEnable() + { + user = (WorldAnalysisUser)target; + } + + public override void OnInspectorGUI() + { + serializedObject.Update(); + + DrawDefaultInspector(); + EditorGUILayout.Space(); + + if (GUILayout.Button("Generate New Creator UUID")) + { + user.UUID = System.Guid.NewGuid().ToString(); + EditorUtility.SetDirty(target); + } + } +} diff --git a/Editor/Scripts/WorldAnalysisUserEditor.cs.meta b/Editor/Scripts/WorldAnalysisUserEditor.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..74303ebefd651ab1b982263b3fd940c1e17bfc37 --- /dev/null +++ b/Editor/Scripts/WorldAnalysisUserEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b0d1b5ae7e5771b4496dfd778bfa031b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Packages.meta b/Runtime/Packages.meta new file mode 100644 index 0000000000000000000000000000000000000000..b6c7aeca1ec8da4b41c26c6fae77efb8761f346e --- /dev/null +++ b/Runtime/Packages.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 953b8657509a139449794a24f2147730 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Packages/websocket-sharp-latest.1.0.2.meta b/Runtime/Packages/websocket-sharp-latest.1.0.2.meta new file mode 100644 index 0000000000000000000000000000000000000000..15642e0d3a8f9637a42e7f53f507c648e2c076de --- /dev/null +++ b/Runtime/Packages/websocket-sharp-latest.1.0.2.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4af05175caa96bb43844e080f1d8701b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Packages/websocket-sharp-latest.1.0.2/.signature.p7s b/Runtime/Packages/websocket-sharp-latest.1.0.2/.signature.p7s new file mode 100644 index 0000000000000000000000000000000000000000..29b82e384cd4bfbf60c118bfe30e6e30bd1d7699 Binary files /dev/null and b/Runtime/Packages/websocket-sharp-latest.1.0.2/.signature.p7s differ diff --git a/Runtime/Packages/websocket-sharp-latest.1.0.2/lib.meta b/Runtime/Packages/websocket-sharp-latest.1.0.2/lib.meta new file mode 100644 index 0000000000000000000000000000000000000000..b83a27ae6b2adea4b3933cad26125ed564976044 --- /dev/null +++ b/Runtime/Packages/websocket-sharp-latest.1.0.2/lib.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1494d109bc218c346ab7622ed734ea86 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Packages/websocket-sharp-latest.1.0.2/lib/netstandard2.0.meta b/Runtime/Packages/websocket-sharp-latest.1.0.2/lib/netstandard2.0.meta new file mode 100644 index 0000000000000000000000000000000000000000..7d2e7f155cabf023f95db07c08c3503c753acea9 --- /dev/null +++ b/Runtime/Packages/websocket-sharp-latest.1.0.2/lib/netstandard2.0.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9d5dbed810c34cc4db0fe224cda88d0b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Packages/websocket-sharp-latest.1.0.2/lib/netstandard2.0/websocket-sharp-latest.dll.meta b/Runtime/Packages/websocket-sharp-latest.1.0.2/lib/netstandard2.0/websocket-sharp-latest.dll.meta new file mode 100644 index 0000000000000000000000000000000000000000..9be2412de27263ba5dd369214fc161c466858683 --- /dev/null +++ b/Runtime/Packages/websocket-sharp-latest.1.0.2/lib/netstandard2.0/websocket-sharp-latest.dll.meta @@ -0,0 +1,23 @@ +fileFormatVersion: 2 +guid: bddbf4bf9ff11da4885638979b82efb2 +labels: +- NuGetForUnity +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 1 + settings: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Packages/websocket-sharp-latest.1.0.2/websocket-sharp-latest.nuspec b/Runtime/Packages/websocket-sharp-latest.1.0.2/websocket-sharp-latest.nuspec new file mode 100644 index 0000000000000000000000000000000000000000..18e382ad69a2b8278b2aab3d31e54b9ac5380f6c --- /dev/null +++ b/Runtime/Packages/websocket-sharp-latest.1.0.2/websocket-sharp-latest.nuspec @@ -0,0 +1,17 @@ + + + + websocket-sharp-latest + 1.0.2 + websocket-sharp-latest + MIT + https://licenses.nuget.org/MIT + websocket-sharp_icon.png + Package Description + https://github.com/garbles-labs/websocket-sharp/releases + + + + + + \ No newline at end of file diff --git a/Runtime/Packages/websocket-sharp-latest.1.0.2/websocket-sharp-latest.nuspec.meta b/Runtime/Packages/websocket-sharp-latest.1.0.2/websocket-sharp-latest.nuspec.meta new file mode 100644 index 0000000000000000000000000000000000000000..667b2c7eb8fbb988a74c062695fe599842cacbf5 --- /dev/null +++ b/Runtime/Packages/websocket-sharp-latest.1.0.2/websocket-sharp-latest.nuspec.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: a9d61c123a66f5b4a8d236c2972a3609 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Packages/websocket-sharp-latest.1.0.2/websocket-sharp_icon.png b/Runtime/Packages/websocket-sharp-latest.1.0.2/websocket-sharp_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a07c30eb38d729691b987ff3ae8597fe3256b999 Binary files /dev/null and b/Runtime/Packages/websocket-sharp-latest.1.0.2/websocket-sharp_icon.png differ diff --git a/Runtime/Packages/websocket-sharp-latest.1.0.2/websocket-sharp_icon.png.meta b/Runtime/Packages/websocket-sharp-latest.1.0.2/websocket-sharp_icon.png.meta new file mode 100644 index 0000000000000000000000000000000000000000..76b216b774fff699b984249323daaaf4c052bf04 --- /dev/null +++ b/Runtime/Packages/websocket-sharp-latest.1.0.2/websocket-sharp_icon.png.meta @@ -0,0 +1,153 @@ +fileFormatVersion: 2 +guid: b3235afb951bf0a4f9e21db48a0937f6 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 13 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 0 + wrapV: 0 + wrapW: 0 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: iPhone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: WebGL + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Scriptables.meta b/Runtime/Scriptables.meta new file mode 100644 index 0000000000000000000000000000000000000000..058c09b1bab8ec6575fc872230f1b2dda37dd350 --- /dev/null +++ b/Runtime/Scriptables.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 24a8b3224329f984c9b1737d44f11163 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Scriptables/WorldAnalysisServer.cs b/Runtime/Scriptables/WorldAnalysisServer.cs new file mode 100644 index 0000000000000000000000000000000000000000..fb21b57acd4b6a498532a676e53cd0b7307a2ed2 --- /dev/null +++ b/Runtime/Scriptables/WorldAnalysisServer.cs @@ -0,0 +1,39 @@ +// +// ARF - Augmented Reality Framework (ETSI ISG ARF) +// +// Copyright 2024 ETSI +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Last change: August 2024 +// + +using UnityEngine; + +namespace ETSI.ARF.WorldAnalysis +{ + [System.Serializable] + [CreateAssetMenu(fileName = "ARFWorldAnalysisServer", menuName = "ARF World Analysis/Create Server", order = 1)] + public class WorldAnalysisServer : ScriptableObject + { + [SerializeField] public string serverName = "myServerName"; + [SerializeField] public string company = ""; + [SerializeField] public string basePath = "https://"; + [SerializeField] public int port = 8080; + + [Space(8)] + [SerializeField] public WorldAnalysisUser currentUser = null; + + public string URI => port == 0 ? basePath : basePath + ":" + port.ToString(); + } +} \ No newline at end of file diff --git a/Runtime/Scriptables/WorldAnalysisServer.cs.meta b/Runtime/Scriptables/WorldAnalysisServer.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..7abd0fffb9fcc28b63065f9585c2337006da5444 --- /dev/null +++ b/Runtime/Scriptables/WorldAnalysisServer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4571d019d0609224aa4a14ed18de30cd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Scriptables/WorldAnalysisUser.cs b/Runtime/Scriptables/WorldAnalysisUser.cs new file mode 100644 index 0000000000000000000000000000000000000000..85faade5a0a7b138d81e0a8e6210c09f18cfa10d --- /dev/null +++ b/Runtime/Scriptables/WorldAnalysisUser.cs @@ -0,0 +1,33 @@ +// +// ARF - Augmented Reality Framework (ETSI ISG ARF) +// +// Copyright 2024 ETSI +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Last change: August 2024 +// + +using UnityEngine; + +namespace ETSI.ARF.WorldAnalysis +{ + [System.Serializable] + [CreateAssetMenu(fileName = "ARFWorldAnalysisUser", menuName = "ARF World Analysis/Create User", order = 1)] + public class WorldAnalysisUser : ScriptableObject + { + [SerializeField] public string userName = "myName"; + [SerializeField] public string company = ""; + [SerializeField] public string UUID = System.Guid.Empty.ToString(); + } +} \ No newline at end of file diff --git a/Runtime/Scriptables/WorldAnalysisUser.cs.meta b/Runtime/Scriptables/WorldAnalysisUser.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..93b285fec331be825e710a4e62a25a83a3ddf88e --- /dev/null +++ b/Runtime/Scriptables/WorldAnalysisUser.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 01f9889f0a04026429aa8459e181e973 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Scripts/OpenAPI/BaseClient.cs b/Runtime/Scripts/OpenAPI/BaseClient.cs new file mode 100644 index 0000000000000000000000000000000000000000..c93808e38b86fb42ae9cfbf4ebb57fd3737b2dbb --- /dev/null +++ b/Runtime/Scripts/OpenAPI/BaseClient.cs @@ -0,0 +1,38 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace ETSI.ARF.OpenAPI.WorldAnalysis +{ + /// + /// Simple class to debug the requests + /// + public class BaseClient + { + static public bool EnableClientLog = true; + public string lastJsonText; + public long lastPayload; + + protected void _prepareRequest(ETSI.ARF.OpenAPI.WorldAnalysis.IHttpClient client, System.Net.Http.HttpRequestMessage request, string url) + { + if (EnableClientLog) + { + Debug.Log("[REST][URL] Send request: " + client.BaseAddress + url); + Debug.Log("[REST][URL] Send request: " + request); + } + } + + protected void _processResponse(ETSI.ARF.OpenAPI.WorldAnalysis.IHttpClient client, System.Net.Http.HttpResponseMessage response) + { + lastJsonText = response.Content.ReadAsStringAsync().Result.ToString(); + lastPayload = response.Content.Headers.ContentLength.Value; + + var status_ = (int)response.StatusCode; + + if (EnableClientLog) + { + Debug.Log("[REST][Data] Status: " + status_ + " Response: " + client.BaseAddress + " Len: " + lastPayload + " JSON: " + lastJsonText); + } + } + } +} \ No newline at end of file diff --git a/Runtime/Scripts/OpenAPI/BaseClient.cs.meta b/Runtime/Scripts/OpenAPI/BaseClient.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..0af7d2c3954aa947ddeaad3e15d96a65ce00ff58 --- /dev/null +++ b/Runtime/Scripts/OpenAPI/BaseClient.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 696362f892252db4ca192c6eccbbfa25 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Scripts/OpenAPI/DataModels.cs b/Runtime/Scripts/OpenAPI/DataModels.cs new file mode 100644 index 0000000000000000000000000000000000000000..0d2864d31d7729442315279c757705276ee5caa1 --- /dev/null +++ b/Runtime/Scripts/OpenAPI/DataModels.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace ETSI.ARF.OpenAPI.WorldAnalysis +{ + public interface IModel + { + public System.Guid Uuid { get; set; } // Bug: SylR: Why is Uuid not capitalized (UUID)??? + + public string ToJson(); + } + + // Class to monitor the server + public class Server : IModel + { + public System.Guid Uuid { get; set; } + public string Name { get; set; } + + public Server(string name) + { + Uuid = Guid.Empty; + Name = name; + } + + public string ToJson() { return Newtonsoft.Json.JsonConvert.SerializeObject(this); } + } + + //public class MatrixPose : Pose + //{ + // [Newtonsoft.Json.JsonProperty("matrixValue", Required = Newtonsoft.Json.Required.AllowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + // public MatrixPoseValue MatrixValue { get; set; } + //} + + // + // Implement here some constructors + // + public partial class Pose : IModel + { + public Pose() + { + Uuid = Guid.NewGuid(); + } + + public string ToJson() { return Newtonsoft.Json.JsonConvert.SerializeObject(this); } + } +} \ No newline at end of file diff --git a/Runtime/Scripts/OpenAPI/DataModels.cs.meta b/Runtime/Scripts/OpenAPI/DataModels.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..ba6ef3620f111f2a823fd0ea0582be00142f58c7 --- /dev/null +++ b/Runtime/Scripts/OpenAPI/DataModels.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 90e60e9d41d419146b3b6207e4ef556e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Scripts/OpenAPI/Generated/WorldAnalysisOpenAPI.cs b/Runtime/Scripts/OpenAPI/Generated/WorldAnalysisOpenAPI.cs index d9ac029a49a0168ec25aba84e3b9d7179aef420b..713ebd5dec71dd6a7bb553d364b7b8ab6869d787 100644 --- a/Runtime/Scripts/OpenAPI/Generated/WorldAnalysisOpenAPI.cs +++ b/Runtime/Scripts/OpenAPI/Generated/WorldAnalysisOpenAPI.cs @@ -1,6 +1,6 @@ //---------------------- // -// Generated using the NSwag toolchain v14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0)) (http://NSwag.org) +// Generated using the NSwag toolchain v14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0)) (http://NSwag.org) // //---------------------- @@ -8,6 +8,7 @@ #pragma warning disable 114 // Disable "CS0114 '{derivedDto}.RaisePropertyChanged(String)' hides inherited member 'dtoBase.RaisePropertyChanged(String)'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword." #pragma warning disable 472 // Disable "CS0472 The result of the expression is always 'false' since a value of type 'Int32' is never equal to 'null' of type 'Int32?' #pragma warning disable 612 // Disable "CS0612 '...' is obsolete" +#pragma warning disable 649 // Disable "CS0649 Field is never assigned to, and will always have its default value null" #pragma warning disable 1573 // Disable "CS1573 Parameter '...' has no matching param tag in the XML comment for ... #pragma warning disable 1591 // Disable "CS1591 Missing XML comment for publicly visible type or member ..." #pragma warning disable 8073 // Disable "CS8073 The result of the expression is always 'false' since a value of type 'T' is never equal to 'null' of type 'T?'" @@ -15,23 +16,25 @@ #pragma warning disable 8603 // Disable "CS8603 Possible null reference return" #pragma warning disable 8604 // Disable "CS8604 Possible null reference argument for parameter" #pragma warning disable 8625 // Disable "CS8625 Cannot convert null literal to non-nullable reference type" -#pragma warning disable CS8765 // Nullability of type of parameter doesn't match overridden member (possibly because of nullability attributes). +#pragma warning disable 8765 // Disable "CS8765 Nullability of type of parameter doesn't match overridden member (possibly because of nullability attributes)." namespace ETSI.ARF.OpenAPI.WorldAnalysis { using System = global::System; - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class WorldAnalysisClient { - private ETSI.ARF.OpenAPI.IHttpClient _httpClient; + private ETSI.ARF.OpenAPI.WorldAnalysis.IHttpClient _httpClient; private static System.Lazy _settings = new System.Lazy(CreateSerializerSettings, true); + private Newtonsoft.Json.JsonSerializerSettings _instanceSettings; #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - public WorldAnalysisClient(ETSI.ARF.OpenAPI.IHttpClient httpClient) + public WorldAnalysisClient(ETSI.ARF.OpenAPI.WorldAnalysis.IHttpClient httpClient) #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. { _httpClient = httpClient; + Initialize(); } private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() @@ -41,13 +44,15 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis return settings; } - protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _settings.Value; } } + protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _instanceSettings ?? _settings.Value; } } static partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings); - partial void PrepareRequest(ETSI.ARF.OpenAPI.IHttpClient client, System.Net.Http.HttpRequestMessage request, string url); - partial void PrepareRequest(ETSI.ARF.OpenAPI.IHttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder); - partial void ProcessResponse(ETSI.ARF.OpenAPI.IHttpClient client, System.Net.Http.HttpResponseMessage response); + partial void Initialize(); + + partial void PrepareRequest(ETSI.ARF.OpenAPI.WorldAnalysis.IHttpClient client, System.Net.Http.HttpRequestMessage request, string url); + partial void PrepareRequest(ETSI.ARF.OpenAPI.WorldAnalysis.IHttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder); + partial void ProcessResponse(ETSI.ARF.OpenAPI.WorldAnalysis.IHttpClient client, System.Net.Http.HttpResponseMessage response); /// /// Test the server availability. @@ -374,7 +379,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis if (sessionID != null) request_.Headers.TryAddWithoutValidation("sessionID", ConvertToString(sessionID, System.Globalization.CultureInfo.InvariantCulture)); - var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(body, _settings.Value); + var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(body, JsonSerializerSettings); var content_ = new System.Net.Http.StringContent(json_); content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); request_.Content = content_; @@ -415,9 +420,22 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis else if (status_ == 405) { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - var result_ = (string)System.Convert.ChangeType(responseData_, typeof(string)); - throw new ApiException("Not supported.", status_, responseData_, headers_, result_, null); + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("Not supported.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); + } + else + if (status_ == 511) + { + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("The secret token is not valid. Please ask an ISG ARF team member for a valid token.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); } else { @@ -551,30 +569,52 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis else if (status_ == 400) { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - var result_ = (string)System.Convert.ChangeType(responseData_, typeof(string)); - throw new ApiException("Bad request.", status_, responseData_, headers_, result_, null); + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("Bad request.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); } else if (status_ == 403) { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - var result_ = (string)System.Convert.ChangeType(responseData_, typeof(string)); - throw new ApiException("Not allowed.", status_, responseData_, headers_, result_, null); + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("Not allowed.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); } else if (status_ == 404) { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - var result_ = (string)System.Convert.ChangeType(responseData_, typeof(string)); - throw new ApiException("Not found.", status_, responseData_, headers_, result_, null); + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("Not found.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); } else if (status_ == 405) { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - var result_ = (string)System.Convert.ChangeType(responseData_, typeof(string)); - throw new ApiException("Not supported.", status_, responseData_, headers_, result_, null); + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("Not supported.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); + } + else + if (status_ == 511) + { + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("The secret token is not valid. Please ask an ISG ARF team member for a valid token.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); } else { @@ -609,7 +649,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis /// List of UUIDs of the Trackables and Anchors to request with the mode representing the context of the Relocalization information (AR device to WorldAnchor/Trackable or WorldAnchor/Trackable to AR device) /// Successful operation. /// A server side error occurred. - public virtual System.Threading.Tasks.Task GetPosesAsync(string token, string sessionID, System.Collections.Generic.IEnumerable uuid) + public virtual System.Threading.Tasks.Task GetPosesAsync(string token, string sessionID, System.Collections.Generic.IEnumerable uuid) { return GetPosesAsync(token, sessionID, uuid, System.Threading.CancellationToken.None); } @@ -623,7 +663,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis /// List of UUIDs of the Trackables and Anchors to request with the mode representing the context of the Relocalization information (AR device to WorldAnchor/Trackable or WorldAnchor/Trackable to AR device) /// Successful operation. /// A server side error occurred. - public virtual Response GetPoses(string token, string sessionID, System.Collections.Generic.IEnumerable uuid) + public virtual Poses GetPoses(string token, string sessionID, System.Collections.Generic.IEnumerable uuid) { return System.Threading.Tasks.Task.Run(async () => await GetPosesAsync(token, sessionID, uuid, System.Threading.CancellationToken.None)).GetAwaiter().GetResult(); } @@ -638,7 +678,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis /// List of UUIDs of the Trackables and Anchors to request with the mode representing the context of the Relocalization information (AR device to WorldAnchor/Trackable or WorldAnchor/Trackable to AR device) /// Successful operation. /// A server side error occurred. - public virtual async System.Threading.Tasks.Task GetPosesAsync(string token, string sessionID, System.Collections.Generic.IEnumerable uuid, System.Threading.CancellationToken cancellationToken) + public virtual async System.Threading.Tasks.Task GetPosesAsync(string token, string sessionID, System.Collections.Generic.IEnumerable uuid, System.Threading.CancellationToken cancellationToken) { if (uuid == null) throw new System.ArgumentNullException("uuid"); @@ -691,7 +731,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis var status_ = (int)response_.StatusCode; if (status_ == 200) { - var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); if (objectResponse_.Object == null) { throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); @@ -701,30 +741,52 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis else if (status_ == 400) { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - var result_ = (string)System.Convert.ChangeType(responseData_, typeof(string)); - throw new ApiException("Bad request.", status_, responseData_, headers_, result_, null); + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("Bad request.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); } else if (status_ == 403) { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - var result_ = (string)System.Convert.ChangeType(responseData_, typeof(string)); - throw new ApiException("Not allowed.", status_, responseData_, headers_, result_, null); + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("Not allowed.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); } else if (status_ == 404) { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - var result_ = (string)System.Convert.ChangeType(responseData_, typeof(string)); - throw new ApiException("Not found.", status_, responseData_, headers_, result_, null); + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("Not found.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); } else if (status_ == 405) { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - var result_ = (string)System.Convert.ChangeType(responseData_, typeof(string)); - throw new ApiException("Not supported.", status_, responseData_, headers_, result_, null); + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("Not supported.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); + } + else + if (status_ == 511) + { + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("The secret token is not valid. Please ask an ISG ARF team member for a valid token.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); } else { @@ -802,7 +864,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis if (sessionID != null) request_.Headers.TryAddWithoutValidation("sessionID", ConvertToString(sessionID, System.Globalization.CultureInfo.InvariantCulture)); - var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(body, _settings.Value); + var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(body, JsonSerializerSettings); var content_ = new System.Net.Http.StringContent(json_); content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); request_.Content = content_; @@ -849,30 +911,52 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis else if (status_ == 400) { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - var result_ = (string)System.Convert.ChangeType(responseData_, typeof(string)); - throw new ApiException("Bad request.", status_, responseData_, headers_, result_, null); + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("Bad request.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); } else if (status_ == 403) { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - var result_ = (string)System.Convert.ChangeType(responseData_, typeof(string)); - throw new ApiException("Not allowed.", status_, responseData_, headers_, result_, null); + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("Not allowed.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); } else if (status_ == 404) { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - var result_ = (string)System.Convert.ChangeType(responseData_, typeof(string)); - throw new ApiException("Not found.", status_, responseData_, headers_, result_, null); + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("Not found.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); } else if (status_ == 405) { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - var result_ = (string)System.Convert.ChangeType(responseData_, typeof(string)); - throw new ApiException("Not supported.", status_, responseData_, headers_, result_, null); + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("Not supported.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); + } + else + if (status_ == 511) + { + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("The secret token is not valid. Please ask an ISG ARF team member for a valid token.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); } else { @@ -997,16 +1081,32 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis else if (status_ == 400) { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - var result_ = (string)System.Convert.ChangeType(responseData_, typeof(string)); - throw new ApiException("Bad request.", status_, responseData_, headers_, result_, null); + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("Bad request.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); } else if (status_ == 404) { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - var result_ = (string)System.Convert.ChangeType(responseData_, typeof(string)); - throw new ApiException("Not found.", status_, responseData_, headers_, result_, null); + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("Not found.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); + } + else + if (status_ == 511) + { + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("The secret token is not valid. Please ask an ISG ARF team member for a valid token.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); } else { @@ -1086,7 +1186,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis if (sessionID != null) request_.Headers.TryAddWithoutValidation("sessionID", ConvertToString(sessionID, System.Globalization.CultureInfo.InvariantCulture)); - var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(body, _settings.Value); + var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(body, JsonSerializerSettings); var content_ = new System.Net.Http.StringContent(json_); content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); request_.Content = content_; @@ -1134,16 +1234,32 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis else if (status_ == 400) { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - var result_ = (string)System.Convert.ChangeType(responseData_, typeof(string)); - throw new ApiException("Bad request.", status_, responseData_, headers_, result_, null); + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("Bad request.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); } else if (status_ == 404) { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - var result_ = (string)System.Convert.ChangeType(responseData_, typeof(string)); - throw new ApiException("Not found.", status_, responseData_, headers_, result_, null); + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("Not found.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); + } + else + if (status_ == 511) + { + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("The secret token is not valid. Please ask an ISG ARF team member for a valid token.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); } else { @@ -1172,9 +1288,9 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis /// End the subscription and the associated callback for collecting a given pose /// /// Subscription UUID to delete. - /// OK, unsubcription successful. + /// Success request. /// A server side error occurred. - public virtual System.Threading.Tasks.Task UnsubscribeFromPoseAsync(string token, string sessionID, System.Guid subscriptionUUID) + public virtual System.Threading.Tasks.Task UnsubscribeFromPoseAsync(string token, string sessionID, System.Guid subscriptionUUID) { return UnsubscribeFromPoseAsync(token, sessionID, subscriptionUUID, System.Threading.CancellationToken.None); } @@ -1186,9 +1302,9 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis /// End the subscription and the associated callback for collecting a given pose /// /// Subscription UUID to delete. - /// OK, unsubcription successful. + /// Success request. /// A server side error occurred. - public virtual string UnsubscribeFromPose(string token, string sessionID, System.Guid subscriptionUUID) + public virtual Success UnsubscribeFromPose(string token, string sessionID, System.Guid subscriptionUUID) { return System.Threading.Tasks.Task.Run(async () => await UnsubscribeFromPoseAsync(token, sessionID, subscriptionUUID, System.Threading.CancellationToken.None)).GetAwaiter().GetResult(); } @@ -1201,9 +1317,9 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis /// End the subscription and the associated callback for collecting a given pose /// /// Subscription UUID to delete. - /// OK, unsubcription successful. + /// Success request. /// A server side error occurred. - public virtual async System.Threading.Tasks.Task UnsubscribeFromPoseAsync(string token, string sessionID, System.Guid subscriptionUUID, System.Threading.CancellationToken cancellationToken) + public virtual async System.Threading.Tasks.Task UnsubscribeFromPoseAsync(string token, string sessionID, System.Guid subscriptionUUID, System.Threading.CancellationToken cancellationToken) { if (subscriptionUUID == null) throw new System.ArgumentNullException("subscriptionUUID"); @@ -1221,7 +1337,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis if (sessionID != null) request_.Headers.TryAddWithoutValidation("sessionID", ConvertToString(sessionID, System.Globalization.CultureInfo.InvariantCulture)); request_.Method = new System.Net.Http.HttpMethod("DELETE"); - request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("text/plain")); + request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); @@ -1254,23 +1370,42 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis var status_ = (int)response_.StatusCode; if (status_ == 200) { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - var result_ = (string)System.Convert.ChangeType(responseData_, typeof(string)); - return result_; + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + return objectResponse_.Object; } else if (status_ == 400) { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - var result_ = (string)System.Convert.ChangeType(responseData_, typeof(string)); - throw new ApiException("Bad request.", status_, responseData_, headers_, result_, null); + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("Bad request.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); } else if (status_ == 404) { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - var result_ = (string)System.Convert.ChangeType(responseData_, typeof(string)); - throw new ApiException("Not found.", status_, responseData_, headers_, result_, null); + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("Not found.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); + } + else + if (status_ == 511) + { + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("The secret token is not valid. Please ask an ISG ARF team member for a valid token.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); } else { @@ -1300,7 +1435,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis /// /// Successful operation. /// A server side error occurred. - public virtual System.Threading.Tasks.Task GetCapabilitiesAsync(string token, string sessionID) + public virtual System.Threading.Tasks.Task GetCapabilitiesAsync(string token, string sessionID) { return GetCapabilitiesAsync(token, sessionID, System.Threading.CancellationToken.None); } @@ -1313,7 +1448,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis /// /// Successful operation. /// A server side error occurred. - public virtual Response2 GetCapabilities(string token, string sessionID) + public virtual Capabilities GetCapabilities(string token, string sessionID) { return System.Threading.Tasks.Task.Run(async () => await GetCapabilitiesAsync(token, sessionID, System.Threading.CancellationToken.None)).GetAwaiter().GetResult(); } @@ -1327,7 +1462,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis /// /// Successful operation. /// A server side error occurred. - public virtual async System.Threading.Tasks.Task GetCapabilitiesAsync(string token, string sessionID, System.Threading.CancellationToken cancellationToken) + public virtual async System.Threading.Tasks.Task GetCapabilitiesAsync(string token, string sessionID, System.Threading.CancellationToken cancellationToken) { var client_ = _httpClient; var disposeClient_ = false; @@ -1374,7 +1509,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis var status_ = (int)response_.StatusCode; if (status_ == 200) { - var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); if (objectResponse_.Object == null) { throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); @@ -1382,6 +1517,16 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis return objectResponse_.Object; } else + if (status_ == 511) + { + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("The secret token is not valid. Please ask an ISG ARF team member for a valid token.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); + } + else { var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); if (objectResponse_.Object == null) @@ -1414,7 +1559,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis /// UUID of the Trackable or Anchor to check support /// Successful operation. /// A server side error occurred. - public virtual System.Threading.Tasks.Task GetSupportAsync(string token, string sessionID, System.Guid trackableOrAnchorUUID) + public virtual System.Threading.Tasks.Task GetSupportAsync(string token, string sessionID, System.Guid trackableOrAnchorUUID) { return GetSupportAsync(token, sessionID, trackableOrAnchorUUID, System.Threading.CancellationToken.None); } @@ -1428,7 +1573,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis /// UUID of the Trackable or Anchor to check support /// Successful operation. /// A server side error occurred. - public virtual Response3 GetSupport(string token, string sessionID, System.Guid trackableOrAnchorUUID) + public virtual Supports GetSupport(string token, string sessionID, System.Guid trackableOrAnchorUUID) { return System.Threading.Tasks.Task.Run(async () => await GetSupportAsync(token, sessionID, trackableOrAnchorUUID, System.Threading.CancellationToken.None)).GetAwaiter().GetResult(); } @@ -1443,7 +1588,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis /// UUID of the Trackable or Anchor to check support /// Successful operation. /// A server side error occurred. - public virtual async System.Threading.Tasks.Task GetSupportAsync(string token, string sessionID, System.Guid trackableOrAnchorUUID, System.Threading.CancellationToken cancellationToken) + public virtual async System.Threading.Tasks.Task GetSupportAsync(string token, string sessionID, System.Guid trackableOrAnchorUUID, System.Threading.CancellationToken cancellationToken) { if (trackableOrAnchorUUID == null) throw new System.ArgumentNullException("trackableOrAnchorUUID"); @@ -1494,7 +1639,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis var status_ = (int)response_.StatusCode; if (status_ == 200) { - var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); if (objectResponse_.Object == null) { throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); @@ -1504,30 +1649,52 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis else if (status_ == 400) { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - var result_ = (string)System.Convert.ChangeType(responseData_, typeof(string)); - throw new ApiException("Bad request.", status_, responseData_, headers_, result_, null); + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("Bad request.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); } else if (status_ == 403) { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - var result_ = (string)System.Convert.ChangeType(responseData_, typeof(string)); - throw new ApiException("Not allowed.", status_, responseData_, headers_, result_, null); + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("Not allowed.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); } else if (status_ == 404) { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - var result_ = (string)System.Convert.ChangeType(responseData_, typeof(string)); - throw new ApiException("Not found.", status_, responseData_, headers_, result_, null); + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("Not found.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); } else if (status_ == 405) { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - var result_ = (string)System.Convert.ChangeType(responseData_, typeof(string)); - throw new ApiException("Not supported.", status_, responseData_, headers_, result_, null); + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("Not supported.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); + } + else + if (status_ == 511) + { + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("The secret token is not valid. Please ask an ISG ARF team member for a valid token.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); } else { @@ -1668,7 +1835,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis /// /// An element representing the result of the pose estimation of an AR device, a Trackable or a WorldAnchor by the World Analysis /// - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class Pose { /// @@ -1712,7 +1879,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis /// /// The pose value /// - [Newtonsoft.Json.JsonProperty("value", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [Newtonsoft.Json.JsonProperty("value", Required = Newtonsoft.Json.Required.AllowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public PoseValue Value { get; set; } /// @@ -1735,7 +1902,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis /// /// Base type to define the pose value /// - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class PoseValue { /// @@ -1759,7 +1926,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis /// /// A pose value that is described with a 4*4 matrix /// - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class MatrixPoseValue : PoseValue { /// @@ -1780,7 +1947,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis /// /// A pose value that is described with a position and a rotation /// - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class VectorQuaternionPoseValue : PoseValue { /// @@ -1807,7 +1974,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis /// /// A pose value in a geodetic coordinate system /// - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class GeodeticPoseValue : PoseValue { [Newtonsoft.Json.JsonProperty("altitude", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] @@ -1843,7 +2010,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis /// /// An object representing the framerate that the World Analysis needs to reach for a given Trackable Type /// - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class PoseConfiguration { [Newtonsoft.Json.JsonProperty("trackableType", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] @@ -1873,7 +2040,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis /// /// Request when subscribing for pose update of a Trackable or a WorldAnchor /// - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class SubscriptionSingleRequest { /// @@ -1915,20 +2082,20 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis /// /// Request when subscribing for pose update of multiple Trackable or a WorldAnchor /// - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class SubscriptionMultipleRequest { /// /// List of UUID of the Trackable or Anchor to subscribe /// [Newtonsoft.Json.JsonProperty("targets", Required = Newtonsoft.Json.Required.Always)] - public System.Collections.Generic.ICollection Targets { get; set; } = new System.Collections.ObjectModel.Collection(); + public System.Collections.Generic.ICollection Targets { get; set; } = new System.Collections.ObjectModel.Collection(); /// /// List of modes representing the context of the Relocalization information (AR device to WorldAnchor/Trackable or WorldAnchor/Trackable to AR device) /// - [Newtonsoft.Json.JsonProperty("mode", Required = Newtonsoft.Json.Required.Always, ItemConverterType = typeof(Newtonsoft.Json.Converters.StringEnumConverter))] - public System.Collections.Generic.ICollection Mode { get; set; } = new System.Collections.ObjectModel.Collection(); + [Newtonsoft.Json.JsonProperty("modes", Required = Newtonsoft.Json.Required.Always, ItemConverterType = typeof(Newtonsoft.Json.Converters.StringEnumConverter))] + public System.Collections.Generic.ICollection Modes { get; set; } = new System.Collections.ObjectModel.Collection(); /// /// Subscription validity delay in millisecond @@ -1956,7 +2123,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis /// /// Response when subscribing for pose update of a Trackable or a WorldAnchor /// - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class SubscriptionSingle { /// @@ -2007,7 +2174,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis /// /// Response when subscribing for pose update of multiple Trackable or a WorldAnchor /// - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class SubscriptionMultiple { [Newtonsoft.Json.JsonProperty("subscriptions", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] @@ -2027,7 +2194,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis /// /// An object representing a supported capability of the World Analysis and its associated metadata /// - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class Capability { [Newtonsoft.Json.JsonProperty("trackableType", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] @@ -2069,7 +2236,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis /// /// An object holding the info of a Trackable`'`s encoding information `:` the data format and the version. /// - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class EncodingInformationStructure { /// @@ -2096,13 +2263,10 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class Error { - [Newtonsoft.Json.JsonProperty("code", Required = Newtonsoft.Json.Required.Always)] - public int Code { get; set; } - - [Newtonsoft.Json.JsonProperty("message", Required = Newtonsoft.Json.Required.Always)] + [Newtonsoft.Json.JsonProperty("message", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public string Message { get; set; } private System.Collections.Generic.IDictionary _additionalProperties; @@ -2119,7 +2283,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis /// /// Mode representing the context of the relocalization information (AR device to WorldAnchor/Trackable or WorldAnchor/Trackable to AR device) /// - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] public enum Mode_WorldAnalysis { @@ -2134,16 +2298,33 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis /// /// A quaternion /// - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class Quaternion : System.Collections.ObjectModel.Collection { } + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Success + { + [Newtonsoft.Json.JsonProperty("message", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Message { get; set; } + + private System.Collections.Generic.IDictionary _additionalProperties; + + [Newtonsoft.Json.JsonExtensionData] + public System.Collections.Generic.IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new System.Collections.Generic.Dictionary()); } + set { _additionalProperties = value; } + } + + } + /// /// Type for trackable /// - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] public enum TrackableType { @@ -2170,7 +2351,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis /// /// Coordinate reference system of the world anchor, a 4*4 matrix (rowmajor) represented by a float vector. /// - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class Transform3D : System.Collections.ObjectModel.Collection { @@ -2179,7 +2360,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis /// /// Trackable or Anchor /// - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] public enum TypeWorldStorage { @@ -2197,7 +2378,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis /// /// Unit of length. /// - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] public enum UnitSystem { @@ -2239,14 +2420,14 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis /// /// A 3 coordinates vector /// - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class Vector3 : System.Collections.ObjectModel.Collection { } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] - public partial class Anonymous + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class UuidAndMode { [Newtonsoft.Json.JsonProperty("uuid", Required = Newtonsoft.Json.Required.Always)] public System.Guid Uuid { get; set; } @@ -2269,7 +2450,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class Body { /// @@ -2302,11 +2483,11 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] - public partial class Response + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Poses { [Newtonsoft.Json.JsonProperty("poses", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] - public System.Collections.Generic.ICollection Poses { get; set; } + public System.Collections.Generic.ICollection Poses1 { get; set; } private System.Collections.Generic.IDictionary _additionalProperties; @@ -2319,11 +2500,11 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] - public partial class Response2 + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Capabilities { [Newtonsoft.Json.JsonProperty("capabilities", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] - public System.Collections.Generic.ICollection Capabilities { get; set; } + public System.Collections.Generic.ICollection Capabilities1 { get; set; } private System.Collections.Generic.IDictionary _additionalProperties; @@ -2336,8 +2517,8 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] - public partial class Response3 + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Supports { [Newtonsoft.Json.JsonProperty("type", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] @@ -2357,7 +2538,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] public enum PoseEstimationState { @@ -2369,7 +2550,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] public enum PoseValueType { @@ -2384,7 +2565,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] public enum GeodeticPoseValueRotationTarget { @@ -2396,7 +2577,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] public enum PoseConfigurationTrackableType { @@ -2420,7 +2601,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] public enum EncodingInformationStructureDataFormat { @@ -2446,7 +2627,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ApiException : System.Exception { public int StatusCode { get; private set; } @@ -2469,7 +2650,7 @@ namespace ETSI.ARF.OpenAPI.WorldAnalysis } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ApiException : ApiException { public TResult Result { get; private set; } diff --git a/Runtime/Scripts/OpenAPI/ResponseObject.cs b/Runtime/Scripts/OpenAPI/ResponseObject.cs new file mode 100644 index 0000000000000000000000000000000000000000..fa21f3d4ff04edaf83f1576c3a3eb7af5384aece --- /dev/null +++ b/Runtime/Scripts/OpenAPI/ResponseObject.cs @@ -0,0 +1,65 @@ +// The Fraunhofer HHI Unity Framework +// ___________ .__ _____ ___ ___ ___ ___ .___ +// \_ _____/___________ __ __ ____ | |__ _____/ ____\___________ / | \ / | \| | +// | __) \_ __ \__ \ | | \/ \| | \ / _ \ __\/ __ \_ __ \ / ~ \/ ~ \ | +// | \ | | \// __ \| | / | \ Y ( <_> ) | \ ___/| | \/ \ Y /\ Y / | +// \___ / |__| (____ /____/|___| /___| /\____/|__| \___ >__| \___|_ / \___|_ /|___| +// \/ \/ \/ \/ \/ \/ \/ +// (C) Fraunhofer HHI, 2024 + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Threading; +using UnityEngine; + +namespace ETSI.ARF.OpenAPI.WorldAnalysis +{ + public class CancelToken + { + protected CancellationTokenSource tokenSource; + protected CancellationToken ct; + + public CancellationToken cancellationToken { get => ct; } + + public void Cancel() + { + tokenSource.Cancel(); + } + } + + public class ResponseObject : CancelToken + { + // Management stuffs + static int ID = 0; + public int transactionId = 0; + public string message = ""; // custom message, type of data... + + // Time monitoring + public TimeSpan DeltaTime { get => responseTime - requestTime; } + public DateTime requestTime; + public DateTime responseTime; + + // Incoming data + public T result; + public int payload; // size of data + + //public string result = ""; // text result + //public object data = null; // custom result + + // Callback + public Action> callback; + + + public ResponseObject(string msg, Action> func = null) + { + requestTime = DateTime.Now; + message = msg; + callback = func; + transactionId = ++ID; + + tokenSource = new CancellationTokenSource(); + ct = tokenSource.Token; + } + } +} \ No newline at end of file diff --git a/Runtime/Scripts/OpenAPI/ResponseObject.cs.meta b/Runtime/Scripts/OpenAPI/ResponseObject.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..0f1afb54c82dbe646694e4340bffebb314c0abdc --- /dev/null +++ b/Runtime/Scripts/OpenAPI/ResponseObject.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 82dc58594acebf747bd716fd00fcfb10 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Scripts/OpenAPI/UnityWebRequestHttpClient.cs b/Runtime/Scripts/OpenAPI/UnityWebRequestHttpClient.cs new file mode 100644 index 0000000000000000000000000000000000000000..c841a48f45d564fe1c3a943478bfd409d7615eb8 --- /dev/null +++ b/Runtime/Scripts/OpenAPI/UnityWebRequestHttpClient.cs @@ -0,0 +1,243 @@ +// +// ARF - Augmented Reality Framework (ETSI ISG ARF) +// +// Copyright 2024 ETSI +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Last change: September 2024 +// + +// Depends on UniTask to support cancellation token and GetAwaiter: https://github.com/Cysharp/UniTask +// Otherwise, the code can be adapted using https://gist.github.com/krzys-h/9062552e33dd7bd7fe4a6c12db109a1a + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Threading; +using System.Threading.Tasks; +//using Cysharp.Threading.Tasks; + +using UnityEngine; +using UnityEngine.Networking; + +namespace ETSI.ARF.OpenAPI.WorldAnalysis +{ + public interface IHttpClient + { + public Uri BaseAddress { get; set; } + public HttpRequestHeaders DefaultRequestHeaders { get; } + + public Task SendAsync(HttpRequestMessage message, HttpCompletionOption option, + CancellationToken token); + + public void Dispose(); + } + + public class BasicHTTPClient : IHttpClient + { + + public BasicHTTPClient() { } + + public BasicHTTPClient(string baseUri) + { + BaseAddress = new Uri(baseUri); + _httpClient.BaseAddress = BaseAddress; + } + + public BasicHTTPClient(Uri baseUri) + { + BaseAddress = baseUri; + _httpClient.BaseAddress = BaseAddress; + } + + public Uri BaseAddress { get; set; } + public HttpRequestHeaders DefaultRequestHeaders => _httpClient.DefaultRequestHeaders; + + private readonly HttpClient _httpClient = new HttpClient(); + + public async Task SendAsync(HttpRequestMessage message, HttpCompletionOption option, CancellationToken token) + { + return await _httpClient.SendAsync(message, option, token); + } + + public void Dispose() + { + _httpClient.Dispose(); + DefaultRequestHeaders.Clear(); + BaseAddress = null; + } + } + + public class UnityWebRequestHttpClient : IHttpClient + { + public UnityWebRequestHttpClient() { } + + public UnityWebRequestHttpClient(string baseUri) + { + BaseAddress = new Uri(baseUri); + } + + public UnityWebRequestHttpClient(Uri baseUri) + { + BaseAddress = baseUri; + } + + public Uri BaseAddress { get; set; } + public HttpRequestHeaders DefaultRequestHeaders => _httpClient.DefaultRequestHeaders; + + private readonly HttpClient _httpClient = new HttpClient(); + + private void AppendARFHeaders(HttpRequestMessage message, UnityWebRequest webRequest) + { + // Add some ARF headers + foreach (var item in message.Headers) + { + try + { + List li = item.Value as List; + if (item.Key == "token") webRequest.SetRequestHeader(item.Key, li[0].ToString()); // add it + if (item.Key == "sessionID") webRequest.SetRequestHeader(item.Key, li[0].ToString()); // add it + } + catch { } // ignore it + } + } + + public async Task SendAsync(HttpRequestMessage message, HttpCompletionOption option, CancellationToken token) + { + var content = await (message.Content?.ReadAsStringAsync() ?? Task.FromResult("")); + var webRequest = GetUnityWebRequest(message.Method.Method, message.RequestUri, content); + + AppendHeaders(webRequest); + + // Add the ARF API headers + AppendARFHeaders(message, webRequest); + + Debug.Log("[HTTP] Request " + webRequest.uri.ToString()); + try + { + //SylR + webRequest.SendWebRequest(); + while (!webRequest.isDone) + { + if (token.IsCancellationRequested) + { + Debug.Log($"Task '{ message.RequestUri }' cancelled"); + token.ThrowIfCancellationRequested(); + } + await Task.Yield(); + } + + //await webRequest + // .SendWebRequest() + // .WithCancellation(cancellationToken: token); + } + catch (Exception) + { + webRequest.Dispose(); + throw; + } + + Debug.Log("[HTTP] Result: " + webRequest.result.ToString()); + + var responseMessage = CreateHttpResponseMessage(webRequest); + webRequest.Dispose(); + + Debug.Log("[HTTP] Response len: " + responseMessage.Content.Headers.ContentLength); + + return responseMessage; + } + + public void Dispose() + { + _httpClient.Dispose(); + DefaultRequestHeaders.Clear(); + BaseAddress = null; + } + + private UnityWebRequest GetUnityWebRequest(string method, Uri endpoint, string content = "") + { + var requestUri = BaseAddress.AbsoluteUri + endpoint; + var webRequest = UnityWebRequest.Get(requestUri); + webRequest.method = method; + + webRequest.disposeUploadHandlerOnDispose = true; + webRequest.disposeDownloadHandlerOnDispose = true; + + if (!string.IsNullOrEmpty(content)) + { + var data = new System.Text.UTF8Encoding().GetBytes(content); + webRequest.uploadHandler = new UploadHandlerRaw(data); + webRequest.SetRequestHeader("Content-Type", "application/json"); + //webRequest.SetRequestHeader("Content-Type", "image/jpeg"); + } + return webRequest; + } + + private void AppendHeaders(UnityWebRequest webRequest) + { + using var enumerator = DefaultRequestHeaders.GetEnumerator(); + + while (enumerator.MoveNext()) + { + var (key, value) = enumerator.Current; + webRequest.SetRequestHeader(key, value.First()); + } + } + + private HttpResponseMessage CreateHttpResponseMessage(UnityWebRequest webRequest) + { + var responseContent = webRequest.downloadHandler?.text; + + var response = new HttpResponseMessage(); + response.Content = new StringContent(responseContent); + response.StatusCode = (HttpStatusCode)webRequest.responseCode; + + Dictionary headers = webRequest.GetResponseHeaders(); + + if (headers != null) + { + Debug.Log("[HTTP] Header: " + headers.Count.ToString()); + foreach (var h in headers) + { + switch (h.Key.ToLower().Trim()) + { + case "content-type": + { + var trimmed = h.Value.ToLower().Split(";").FirstOrDefault(); + response.Content.Headers.ContentType = new MediaTypeHeaderValue(trimmed); + break; + } + case "content-length": + response.Content.Headers.ContentLength = long.Parse(h.Value); + break; + + default: + if (h.Value == "gzip") + { + // bug??? + } + else + response.Headers.Add(h.Key, h.Value); + break; + } + } + } + return response; + } + } + +} \ No newline at end of file diff --git a/Runtime/Scripts/OpenAPI/UnityWebRequestHttpClient.cs.meta b/Runtime/Scripts/OpenAPI/UnityWebRequestHttpClient.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..7524d3a6df1ef4571c48f2fb69cf16df944ae7b4 --- /dev/null +++ b/Runtime/Scripts/OpenAPI/UnityWebRequestHttpClient.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4aa105d9487dc27408feffefde9e4475 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Scripts/OpenAPI/WorldAnalysisClient.cs b/Runtime/Scripts/OpenAPI/WorldAnalysisClient.cs new file mode 100644 index 0000000000000000000000000000000000000000..852ee38e38cc2939a5ae0f73f3394378ddb4b4a4 --- /dev/null +++ b/Runtime/Scripts/OpenAPI/WorldAnalysisClient.cs @@ -0,0 +1,28 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Networking; + +namespace ETSI.ARF.OpenAPI.WorldAnalysis +{ + /// + /// Catch the pre/pos request methods from the autogenerated classes + /// + public partial class WorldAnalysisClient : BaseClient + { + partial void PrepareRequest(ETSI.ARF.OpenAPI.WorldAnalysis.IHttpClient client, System.Net.Http.HttpRequestMessage request, string url) + { + _prepareRequest(client, request, url); + } + + partial void PrepareRequest(ETSI.ARF.OpenAPI.WorldAnalysis.IHttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder) + { + // do something... + } + + partial void ProcessResponse(ETSI.ARF.OpenAPI.WorldAnalysis.IHttpClient client, System.Net.Http.HttpResponseMessage response) + { + _processResponse(client, response); + } + } +} \ No newline at end of file diff --git a/Runtime/Scripts/OpenAPI/WorldAnalysisClient.cs.meta b/Runtime/Scripts/OpenAPI/WorldAnalysisClient.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..077447f195474d1946102043313d4a3d3962d465 --- /dev/null +++ b/Runtime/Scripts/OpenAPI/WorldAnalysisClient.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 748d04737c53fc04697ac6888226e399 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Scripts/REST.meta b/Runtime/Scripts/REST.meta new file mode 100644 index 0000000000000000000000000000000000000000..29c8716969dec7d6c68b209bced78f0a55b1e777 --- /dev/null +++ b/Runtime/Scripts/REST.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6f0fd52fd30564a4c838a545fe0d00ec +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Scripts/REST/AdminRequest.cs b/Runtime/Scripts/REST/AdminRequest.cs new file mode 100644 index 0000000000000000000000000000000000000000..048b10cd7e23a1a039c1386bdf6bebb90db61a43 --- /dev/null +++ b/Runtime/Scripts/REST/AdminRequest.cs @@ -0,0 +1,113 @@ +// +// ARF - Augmented Reality Framework (ETSI ISG ARF) +// +// Copyright 2024 ETSI +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Last change: March 2024 +// + +using System; +using System.Threading.Tasks; +using UnityEngine; + +using ETSI.ARF.OpenAPI; +using ETSI.ARF.OpenAPI.WorldAnalysis; + +namespace ETSI.ARF.WorldAnalysis.REST +{ + public class AdminRequest : RequestBase + { + #region Test methods + static public void CheckServer(WorldAnalysisServer wa) + { + string ping = AdminRequest.PingSync(wa); + string state = AdminRequest.AdminSync(wa); + string ver = AdminRequest.VersionSync(wa); + Debug.Log("[REST] WA Ping: " + ping); + Debug.Log("[REST] WA State: " + state); + Debug.Log("[REST] WA Version: " + ver); + } + #endregion + + // + // Wrapper for the endpoints + // + static public string PingSync(WorldAnalysisServer ws) + { + wsServer = ws; + var httpClient = new BasicHTTPClient(ws.URI); + apiClient = new WorldAnalysisClient(httpClient); + + string response = apiClient.GetPing(); + return response; + } + + static public ResponseObject PingAsync(WorldAnalysisServer ws, Action> func) + { + wsServer = ws; + var httpClient = new UnityWebRequestHttpClient(ws.URI); + apiClient = new WorldAnalysisClient(httpClient); + + Debug.Log("[REST] Request Ping..."); + ResponseObject ro = new ResponseObject("Request Ping", func); + apiClient.GetPingAsync(ro.cancellationToken).ContinueWith(OnReceiveObject, ro); + return ro; + } + + static public string AdminSync(WorldAnalysisServer ws) + { + wsServer = ws; + var httpClient = new BasicHTTPClient(ws.URI); + apiClient = new WorldAnalysisClient(httpClient); + + string response = apiClient.GetAdmin(); + return response; + } + + static public ResponseObject AdminAsync(WorldAnalysisServer ws, Action> func) + { + wsServer = ws; + var httpClient = new UnityWebRequestHttpClient(ws.URI); + apiClient = new WorldAnalysisClient(httpClient); + + Debug.Log("[REST] Request Admin..."); + ResponseObject ro = new ResponseObject("Request Admin", func); + apiClient.GetAdminAsync(ro.cancellationToken).ContinueWith(OnReceiveObject, ro); + return ro; + } + + static public string VersionSync(WorldAnalysisServer ws) + { + wsServer = ws; + var httpClient = new BasicHTTPClient(ws.URI); + apiClient = new WorldAnalysisClient(httpClient); + + string response = apiClient.GetVersion(); + return response; + } + + static public ResponseObject VersionAsync(WorldAnalysisServer ws, Action> func) + { + wsServer = ws; + var httpClient = new UnityWebRequestHttpClient(ws.URI); + apiClient = new WorldAnalysisClient(httpClient); + + Debug.Log("[REST] Request Version..."); + ResponseObject ro = new ResponseObject("Request Version", func); + apiClient.GetVersionAsync(ro.cancellationToken).ContinueWith(OnReceiveObject, ro); + return ro; + } + } +} diff --git a/Runtime/Scripts/REST/AdminRequest.cs.meta b/Runtime/Scripts/REST/AdminRequest.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..29a5fd8305acfc92e3b7b9ac33b9b0ebc5c4bbaa --- /dev/null +++ b/Runtime/Scripts/REST/AdminRequest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f287a535887d14c46859e33386b90b0e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Scripts/REST/RequestBase.cs b/Runtime/Scripts/REST/RequestBase.cs new file mode 100644 index 0000000000000000000000000000000000000000..6650e8f0da7986b274e9ce020a9d915299464933 --- /dev/null +++ b/Runtime/Scripts/REST/RequestBase.cs @@ -0,0 +1,79 @@ +// +// ARF - Augmented Reality Framework (ETSI ISG ARF) +// +// Copyright 2024 ETSI +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Last change: March 2024 +// + +using System; +using System.Threading.Tasks; +using System.Collections.Generic; +using UnityEngine; + +using ETSI.ARF.OpenAPI; +using ETSI.ARF.OpenAPI.WorldAnalysis; + +namespace ETSI.ARF.WorldAnalysis.REST +{ + public class RequestBase // where T : Trackable, WorldAnchor, WorldLink + { + static protected WorldAnalysisServer wsServer; + static protected WorldAnalysisClient apiClient; + + static protected string token = "ARF_Permission"; + + // Cache the current list + static public Dictionary listOfObjects = new Dictionary(); + + + // + // Helpers + // + static protected void OnReceiveObject(Task t, object id) + { + if (t.IsCompleted) + { + ResponseObject o = (ResponseObject)id; + o.responseTime = DateTime.Now; + o.result = t.Result; + Debug.Log($"[REST] Server Response = {o.result.ToString()} (ID={o.transactionId}, Msg={o.message})"); + + o.callback?.Invoke(o); + } + else Debug.Log("[REST] OpenAPI Timeout!"); + } + + static protected void OnReceiveListOfObjects(Task> t, object id) where TObj : IModel + { + if (t.IsCompleted) + { + ResponseObject> o = (ResponseObject>)id; + o.responseTime = DateTime.Now; + o.result = t.Result; + Debug.Log($"[REST] Server Response = Got {o.result.Count} entrie(s) (ID={o.transactionId}, Msg={o.message})"); + + listOfObjects.Clear(); + foreach (var i in o.result) + { + listOfObjects.Add(i.Uuid, i); + } + o.callback?.Invoke(o); + } + else Debug.Log("[REST] OpenAPI Timeout!"); + } + + } +} diff --git a/Runtime/Scripts/REST/RequestBase.cs.meta b/Runtime/Scripts/REST/RequestBase.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..2bb32b0f9b414c3d10937f86fc75b89a6d599183 --- /dev/null +++ b/Runtime/Scripts/REST/RequestBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c6453e5289606a848ae29ddffa0f7288 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Scripts/WorldAnalysisInfo.cs b/Runtime/Scripts/WorldAnalysisInfo.cs new file mode 100644 index 0000000000000000000000000000000000000000..b461d5e4feb56906eb920c21d5e4c8aca637d4e5 --- /dev/null +++ b/Runtime/Scripts/WorldAnalysisInfo.cs @@ -0,0 +1,45 @@ +// +// ARF - Augmented Reality Framework (ETSI ISG ARF) +// +// Copyright 2024 ETSI +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Last change: August 2024 +// + +using ETSI.ARF.WorldAnalysis; +using UnityEngine; + +public class WorldAnalysisInfo : MonoBehaviour +{ + public WorldAnalysisServer worldAnalysisServer; + + //public bool isServerAlive() + //{ + // if (worldStorageServer == null) return false; + // return !string.IsNullOrEmpty(ETSI.ARF.WorldStorage.REST.AdminRequest.Ping(worldStorageServer)); + //} + + //public string GetServerState() + //{ + // if (worldStorageServer == null) return "No Server Defined!"; + // return ETSI.ARF.WorldStorage.REST.AdminRequest.GetAdminInfo(worldStorageServer); + //} + + //public string GetAPIVersion() + //{ + // if (worldStorageServer == null) return "Unknown Version!"; + // return ETSI.ARF.WorldStorage.REST.AdminRequest.GetVersion(worldStorageServer); + //} +} diff --git a/Runtime/Scripts/WorldAnalysisInfo.cs.meta b/Runtime/Scripts/WorldAnalysisInfo.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..3190dcd83b56ce0b5aace0a0ae69d234922dee5b --- /dev/null +++ b/Runtime/Scripts/WorldAnalysisInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 269d5f98c3c478c4983c24ec09d10a70 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Scripts/WorldAnalysisInterface.cs b/Runtime/Scripts/WorldAnalysisInterface.cs index 1efeacdad1832e8406ed9ec7c9d57c21e32dfc3f..416f91798a8f0c67f50950f8cdc6a44911ef9be5 100644 --- a/Runtime/Scripts/WorldAnalysisInterface.cs +++ b/Runtime/Scripts/WorldAnalysisInterface.cs @@ -151,7 +151,7 @@ public interface WorldAnalysisInterface /// /// id of the subscription /// /// The unsubscription has been performed or not - public InformationSubscriptionResult UnSubscribeToPose(Guid subscriptionUUID); + public InformationSubscriptionResult UnsubscribeFromPose(Guid subscriptionUUID); #endregion diff --git a/Runtime/Scripts/WorldAnalysisREST.cs b/Runtime/Scripts/WorldAnalysisREST.cs index 5c18cebd58911b541edc3ef1a2809d7ac73a6b1a..3b20a5224448429ad0f06188cadd06afa16faa3a 100644 --- a/Runtime/Scripts/WorldAnalysisREST.cs +++ b/Runtime/Scripts/WorldAnalysisREST.cs @@ -1,11 +1,61 @@ +using System; +using System.Collections; +using System.Collections.Generic; using UnityEngine; using ETSI.ARF.OpenAPI.WorldAnalysis; +using ETSI.ARF.WorldAnalysis; using static WorldAnalysisInterface; -using System; +using ETSI.ARF.WorldAnalysis.REST; + +using UnityEngine.Events; //Implementation of the WorldAnalysis interface -public class WorldAnalysisREST : MonoBehaviour, WorldAnalysisInterface +public partial class WorldAnalysisREST : MonoBehaviour, WorldAnalysisInterface { + [Serializable] + public class StringEvent : UnityEvent { } + + // + // Inspector variables + // + + // Name to register the client to the World Analysis + public string modulename = "UnityValidationApp"; + + + /// + /// WorldSAnalysisServer + /// + public WorldAnalysisServer waServer; + public string token = "ETSI-ARF-STF"; + public string sessionID = "ARF-STF669"; + + [Space(8)] + public bool isDebug = false; + + // + // Private members + // + private WorldAnalysisClient apiClient; // For sync calls + private WorldAnalysisClient apiClientAsync; // For async calls + + // + // Management of subscriptions + // + /// + /// Dictionnary of susbscription informations for poses, for each item, stored using the UUID of the item (anchor/trackable) + /// + private Dictionary subscriptionsPoses; + + public struct SubscriptionInfo + { + public ETSI.ARF.OpenAPI.WorldAnalysis.Pose pose; + + public Guid uuid; // id of subscription (id is defined by the WA server) + public Guid uuidTarget; // id trackable or anchor + public float timeValidity; //The duration of the validity of the subscription + public PoseCallback callback; + } #region Unity_Methods @@ -14,6 +64,18 @@ public class WorldAnalysisREST : MonoBehaviour, WorldAnalysisInterface /// protected void Awake() { + Instance = this; + //m_relocalizationInformations = new Dictionary(); + //m_computedPoses = new Dictionary(); + subscriptionsPoses = new Dictionary(); + + // sync + var httpClient = new BasicHTTPClient(waServer.URI); + apiClient = new WorldAnalysisClient(httpClient); + + // async + //var httpClientAsync = new UnityWebRequestHttpClient(waServer.URI); + //apiClientAsync = new WorldAnalysisClient(httpClientAsync); } /// @@ -28,74 +90,348 @@ public class WorldAnalysisREST : MonoBehaviour, WorldAnalysisInterface /// protected void Update() { + ManageSubscriptionValidity(); + + // todo: Call subscription callback(s) here or in the websocket?!? + foreach (KeyValuePair subPose in subscriptionsPoses) + { + } } + private void OnDestroy() + { + WebSocketClient_Close(); + } + + #endregion + + #region Test methods + public void PrintCapabilities(Capability[] capabilities) + { + string res = ""; + Debug.Log("[REST] Got " + capabilities.Length + " capabilities."); + foreach (var item in capabilities) + { + res += "\nCapability: " + item.TrackableType + " Version: " + item.EncodingInformation.Version; + } + res += "\nEnd of capabilities."; + Debug.Log("[REST] Capabilities: " + res); + } #endregion + #region Lifecycle + /// + /// Check the validity of all subscriptions and delete one if needed + /// + protected void ManageSubscriptionValidity() + { + if (subscriptionsPoses.Count == 0) return; - #region ARF_API + List subscriptionToDelete = new List(); + foreach (KeyValuePair sub in subscriptionsPoses) + { + float validity = sub.Value.timeValidity; + if (Time.time > validity) + { + subscriptionToDelete.Add(sub.Key); + } + } + foreach (Guid s in subscriptionToDelete) + { + Debug.Log("ETSI ARF : Subscription deleted " + s); + subscriptionsPoses.Remove(s); + } + } + #endregion - public AskFrameRateResult SetPoseEstimationFramerate(string token, PoseConfigurationTrackableType type, EncodingInformationStructure encodingInformation, int minimumFramerate) + #region ARF_API + // + // Implementation of the endpoints + // + public AskFrameRateResult SetPoseEstimationFramerate(string token, PoseConfigurationTrackableType type, EncodingInformationStructure encodingInformation, int minimumFramerate) { - return AskFrameRateResult.NOT_SUPPORTED; ///We cannot set any framerate for tracking on ARKit and ARCore + PoseConfiguration poseConfig = new PoseConfiguration(); + poseConfig.TrackableType = type; + poseConfig.EncodingInformation = encodingInformation; + poseConfig.Framerate = minimumFramerate; + apiClient.ConfigureFramerate(token, sessionID, poseConfig); + return AskFrameRateResult.OK; } public PoseEstimationResult GetLastPose(string token, Guid uuid, Mode_WorldAnalysis mode, out ETSI.ARF.OpenAPI.WorldAnalysis.Pose pose) { - pose = null; - return PoseEstimationResult.OK; + pose = apiClient.GetPose(token, sessionID, uuid, mode); + return pose != null ? PoseEstimationResult.OK : PoseEstimationResult.NOT_SUPPORTED; } - public PoseEstimationResult[] GetLastPoses(string token, Guid[] uuids, Mode_WorldAnalysis [] modes, out ETSI.ARF.OpenAPI.WorldAnalysis.Pose[] poses) + public PoseEstimationResult[] GetLastPoses(string token, Guid[] uuids, Mode_WorldAnalysis[] modes, out ETSI.ARF.OpenAPI.WorldAnalysis.Pose[] poses) + { + if (uuids.Length != modes.Length) + { + Debug.LogError("[REST] ETSI ARF: Get poses: uuids and modes array do no have the same length"); + poses = null; + return null; + } + PoseEstimationResult[] resul = new PoseEstimationResult[uuids.Length]; + poses = new ETSI.ARF.OpenAPI.WorldAnalysis.Pose[uuids.Length]; + List uuidList = new List(); + Poses poses_ = apiClient.GetPoses(token, sessionID, uuidList.ToArray()); + List posesList = poses_.Poses1 as List; + + if (poses_ != null && posesList != null && posesList.Count > 0) + { + for (int i = 0; i < uuids.Length; i++) + { + PoseEstimationResult poseResult = new PoseEstimationResult(); + resul[i] = poseResult; + poses[i] = posesList[i]; + } + return resul; + } + else + { + poses = null; + return null; + } + } + + private string CreateWebsocket_URL(string originalURL) { - poses = null; - return null; + string uri = originalURL; + + // + // Overwrite server setting for testing local/extra servers + // + //if (isDebug) uri = "ws://localhost:61788/ws"; // for tests + //if (isDebug) uri = "wss://localhost:44301/ws"; // for tests + + return uri; } public InformationSubscriptionResult SubscribeToPose(string token, Guid uuid, Mode_WorldAnalysis mode, PoseCallback callback, ref int validity, out Guid subscriptionUUID) { - subscriptionUUID = Guid.Empty; + // Todo: Maintain the callback to the subscription id + // Get capabilities? + // Get reloc info? + + SubscriptionSingleRequest body = new SubscriptionSingleRequest(); + body.Target = uuid; + body.Mode = mode; + body.Validity = validity; + body.WebhookUrl = callback != null ? "" : "https:\\..."; // empty -> app will use websockets (client)! + + // Get subscription info from the REST server + SubscriptionSingle response = apiClient.SubscribeToPose(token, sessionID, body); + subscriptionUUID = response.Uuid; + validity = response.Validity; + + //SubscriptionMultipleRequest body_m = new SubscriptionMultipleRequest(); + //body_m.Targets = new List(); + //body_m.Mode = new List(); + //body_m.Validity = validity; + //body_m.WebhookUrl = callback == null ? "" : "https:\\..."; // empty -> app will use websockets (client)! + //SubscriptionMultiple response = apiClient.SubscribeToPose(token, sessionID, body_m); + + // We add the subscription + SubscriptionInfo sub = new SubscriptionInfo(); + sub.uuid = subscriptionUUID; + sub.uuidTarget = uuid; + sub.timeValidity = Time.time + (validity / 1000.0f); + sub.callback = callback; + + sub.pose = new ETSI.ARF.OpenAPI.WorldAnalysis.Pose(); + sub.pose.Mode = mode; + + subscriptionsPoses.Add(sub.uuid, sub); + + if (!string.IsNullOrEmpty(response.WebhookUrl)) + { + // Create a REST server so that the WA server can send pose update to it + string webhookUrl = response.WebhookUrl; + + // Close other communication channel + WebSocketClient_Close(); + + // How to auto-generate the C# REST webhook server for pose for Unity? + WebHookServer_Create(webhookUrl); + } + else if (!string.IsNullOrEmpty(response.WebsocketUrl)) + { + // Create the WebSockets client here (NOT in the scene scripts) + + // Close other communication channel + WebHookServer_Close(); + + // Open the websocket + if (webSocket == null) WebSocketClient_Create(CreateWebsocket_URL(response.WebsocketUrl)); // only one instance + } + else throw new Exception("[REST] No valid URL in server reponse."); return InformationSubscriptionResult.OK; } - public InformationSubscriptionResult[] SubscribeToPoses(string token, Guid[] uuids, Mode_WorldAnalysis [] modes, PoseCallback callback, ref int validity, out Guid[] subscriptionUUIDs) + public InformationSubscriptionResult[] SubscribeToPoses(string token, Guid[] uuids, Mode_WorldAnalysis[] modes, PoseCallback callback, ref int validity, out Guid[] subscriptionUUIDs) { - subscriptionUUIDs = null; - return null; + if (uuids.Length != 0 && uuids.Length == modes.Length) + { + InformationSubscriptionResult[] resul = new InformationSubscriptionResult[uuids.Length]; + subscriptionUUIDs = new Guid[uuids.Length]; + for (int i = 0; i < uuids.Length; i++) + { + resul[i] = SubscribeToPose(token, uuids[i], modes[i], callback, ref validity, out subscriptionUUIDs[i]); + } + return resul; + } + else + { + Debug.LogError("[REST] ETSI ARF: Subscribe poses: uuids and modes array do no have the same length"); + subscriptionUUIDs = null; + return null; + } } public InformationSubscriptionResult GetSubsription(string token, Guid subscriptionUUID, out PoseCallback callback, out Guid target, out Mode_WorldAnalysis mode, out int validity) { + // default callback = null; target = Guid.Empty; mode = Mode_WorldAnalysis.TRACKABLES_TO_DEVICE; validity = 0; - return InformationSubscriptionResult.OK; + + if (subscriptionsPoses.ContainsKey(subscriptionUUID)) + { + // Check the server subscription + SubscriptionSingle sub = apiClient.GetSubscription(token, sessionID, subscriptionUUID); + + // Check local one + if (sub.Uuid == subscriptionUUID) + { + SubscriptionInfo subInfo = subscriptionsPoses[subscriptionUUID]; + callback = subInfo.callback; + target = subInfo.uuidTarget; + mode = subInfo.pose.Mode; + float validitySeconds = subInfo.timeValidity - Time.time; + validity = (int)validitySeconds * 1000;// conversion in ms + + // Compare both + if (target == sub.Target && mode == sub.Mode && validity == sub.Validity) + return InformationSubscriptionResult.OK; + else + return InformationSubscriptionResult.NOT_ALLOWED; + } + } + return InformationSubscriptionResult.UNKNOWN_ID; } public InformationSubscriptionResult UpdateSubscription(string token, Guid subscriptionUUID, Mode_WorldAnalysis mode, int validity, PoseCallback callback) { - return InformationSubscriptionResult.OK; + // default + callback = null; + mode = Mode_WorldAnalysis.TRACKABLES_TO_DEVICE; + validity = 0; + + if (subscriptionsPoses.ContainsKey(subscriptionUUID)) + { + SubscriptionInfo sub = subscriptionsPoses[subscriptionUUID]; + PoseCallback oldCB = sub.callback; + + Body newSub = new Body(); + newSub.Mode = mode; + newSub.Validity = validity; + newSub.WebhookUrl = callback == null ? "" : "https:\\..."; // empty -> app will use websockets (client)! + + // Update subscription info in the REST server + SubscriptionSingle response = apiClient.UpdateSubscription(token, sessionID, subscriptionUUID, newSub); + + // Update local data + sub.pose.Mode = response.Mode; + sub.callback = callback; + sub.timeValidity = Time.time + (validity / 1000.0f); + + // + // Recreate server/connection to ws only if someone changed! + // + if (oldCB != null && callback == null && !string.IsNullOrEmpty(response.WebhookUrl)) + { + // Create a REST server so that the WA server can send pose update to it + string webhookUrl = response.WebhookUrl; + + // Close other communication channel + WebSocketClient_Close(); + + // How to auto-generate the C# REST server for pose for Unity? + WebHookServer_Create(webhookUrl); + } + else if (oldCB == null && callback != null && !string.IsNullOrEmpty(response.WebsocketUrl)) + { + // Create the WebSockets client here (NOT in the scene scripts) + + // Close other communication channel + WebHookServer_Close(); + + // Open the websocket? + if (webSocket == null) WebSocketClient_Create(CreateWebsocket_URL(response.WebsocketUrl)); + } + else throw new Exception("[REST] No valid URL in server reponse."); + + return InformationSubscriptionResult.OK; + } + return InformationSubscriptionResult.UNKNOWN_ID; } - public InformationSubscriptionResult UnSubscribeToPose(Guid subscriptionUUID) + public InformationSubscriptionResult UnsubscribeFromPose(Guid subscriptionUUID) { - return InformationSubscriptionResult.OK; + if (subscriptionsPoses.ContainsKey(subscriptionUUID)) + { + apiClient.UnsubscribeFromPose(token, sessionID, subscriptionUUID); + subscriptionsPoses.Remove(subscriptionUUID); + + if (subscriptionsPoses.Count == 0) + { + // Close the connection via websockets + WebSocketClient_Close(); + } + return InformationSubscriptionResult.OK; + } + return InformationSubscriptionResult.UNKNOWN_ID; } public CapabilityResult GetCapabilities(string token, out Capability[] capabilities) { - capabilities = null; - return CapabilityResult.OK; + Capabilities cap = apiClient.GetCapabilities(token, sessionID); + if (cap == null || cap.Capabilities1 == null || cap.Capabilities1.Count == 0) + { + capabilities = null; + return CapabilityResult.FAIL; + } + else + { + capabilities = new Capability[cap.Capabilities1.Count]; + cap.Capabilities1.CopyTo(capabilities, 0); + return CapabilityResult.OK; + } } - public CapabilityResult GetCapability(string token, Guid uuid, out bool isSupported, out TypeWorldStorage type, out Capability [] capability) + public CapabilityResult GetCapability(string token, Guid uuid, out bool isSupported, out TypeWorldStorage type, out Capability[] capability) { isSupported = false; type = TypeWorldStorage.UNKNOWN; capability = null; - return CapabilityResult.OK; + + Supports cap = apiClient.GetSupport(token, sessionID, uuid); + if (cap == null || cap.Capabilities == null || cap.Capabilities.Count == 0) + { + isSupported = false; + capability = null; + return CapabilityResult.FAIL; + } + else + { + isSupported = true; + capability = new Capability[cap.Capabilities.Count]; + cap.Capabilities.CopyTo(capability, 0); + return CapabilityResult.OK; + } } #endregion diff --git a/Runtime/Scripts/WorldAnalysisREST_WebSockets.cs b/Runtime/Scripts/WorldAnalysisREST_WebSockets.cs new file mode 100644 index 0000000000000000000000000000000000000000..e2adc631c9e6f75ff552f7d0cb6a4776e5a92ae7 --- /dev/null +++ b/Runtime/Scripts/WorldAnalysisREST_WebSockets.cs @@ -0,0 +1,122 @@ +#define IS_HHI_LAN + +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using Newtonsoft.Json; +using WebSocketSharp; + +using ETSI.ARF.OpenAPI.WorldAnalysis; +using static WorldAnalysisInterface; + +//Implementation of the WorldAnalysis interface +public partial class WorldAnalysisREST +{ + // + // Inspector variables + // + public StringEvent webSocketMessage; + + // + // Private members + // + private WebSocketSharp.WebSocket webSocket = null; // For WebSockets + + #region Communication system for WebSockets + public WebSocket WebSocketClient_Create(string url) + { + if (webSocket != null) return webSocket; + + string _url = url; + +#if IS_HHI_LAN + _url = "ws://192.168.20.29:8084/ws"; + Debug.LogWarning("[WS] Changing the websocket URL to: " + _url + " (local network VM, HHI)"); +#endif + + webSocket = new WebSocketSharp.WebSocket(_url); + + // + // Define standard callbacks + // + webSocket.OnOpen += (sender, e) => + { + Debug.Log("[WS] Connected"); + webSocket.Send("RegisterClient=" + modulename); + }; + webSocket.OnClose += (sender, e) => + { + Debug.Log("[WS] Disconnected"); + }; + webSocket.OnMessage += (sender, e) => WebSocketClient_OnReceive(e.Data); + webSocket.OnError += (sender, e) => Debug.Log("[WS] Websocket error!"); + webSocket.Connect(); + + return webSocket; + } + + private void WebSocketClient_Close() + { + if (webSocket != null) + { + webSocket.Send("UnregisterClient=" + modulename); + webSocket.Close(); + webSocket = null; + } + } + + public void WebSocketClient_Send(string msg) + { + webSocket?.Send(msg); + } + + bool isRegistered = false; + public void WebSocketClient_OnReceive(string serverMessage) + { + //Debug.Log("[WS] Receiving: " + data); + + if (serverMessage.Contains("You are now registered")) + { + isRegistered = true; + Debug.Log($"[WS] {serverMessage }"); + //Debug.Log($"[WS] Registration of { modulename } was succesfull."); + } + else if (isRegistered) + { + if (serverMessage == "PoseStop") + { + //SetColor(Color.yellow); + } + else if (serverMessage == "PoseIsNowSubscribed") + { + } + else if (serverMessage == "PoseIsNowUnubscribed") + { + } + else if (serverMessage.StartsWith("NewPose=") && serverMessage.Contains("estimationState")) + { + // Handle the new pose + string _str = serverMessage.Substring("NewPose=".Length); + ETSI.ARF.OpenAPI.WorldAnalysis.Pose pose = JsonConvert.DeserializeObject(_str); + //Debug.Log("[WS] JSON - my new pose : " + pose.ToJson()); + + // to check: p.Confidence? + + PoseEstimationResult res = pose.EstimationState == PoseEstimationState.OK ? PoseEstimationResult.OK : PoseEstimationResult.FAILURE; + + // Look for the corresponding callbacks + foreach (var item in subscriptionsPoses.Values) + { + if (item.uuidTarget == pose.Uuid) + { + item.pose.Value = pose.Value; + item.callback(res, pose); + } + } + } + else webSocketMessage?.Invoke(serverMessage); + } + } +#endregion +} \ No newline at end of file diff --git a/Runtime/Scripts/WorldAnalysisREST_WebSockets.cs.meta b/Runtime/Scripts/WorldAnalysisREST_WebSockets.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..31b43338f4f2d50805ff7c31a3e84b9565b117a2 --- /dev/null +++ b/Runtime/Scripts/WorldAnalysisREST_WebSockets.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7b7bcc535a949e24283db7e23c51dc46 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Scripts/WorldAnalysisREST_Webhook.cs b/Runtime/Scripts/WorldAnalysisREST_Webhook.cs new file mode 100644 index 0000000000000000000000000000000000000000..1b4a981f3d8769445c984bc24b3b35daa178e690 --- /dev/null +++ b/Runtime/Scripts/WorldAnalysisREST_Webhook.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using ETSI.ARF.OpenAPI.WorldAnalysis; +using ETSI.ARF.WorldAnalysis; +using ETSI.ARF.WorldAnalysis.REST; + +//Implementation of the WorldAnalysis interface +public partial class WorldAnalysisREST +{ + // + // Inspector variables + // + public StringEvent webhookMessage; + private bool webhookRunning = false; + + #region Communication system for WebHooks + private void WebHookServer_Create(string url) + { + webhookRunning = true; + throw new Exception("[API] WebHookServer_Create(): Not implemented!"); + } + + private void WebHookServer_Close() + { + if (webhookRunning) + { + webhookRunning = false; + throw new Exception("[API] WebHookServer_Close(): Not implemented!"); + } + } + + private object WebHookServer_OnReceive() + { + throw new Exception("[API] WebHookServer_OnReceive(): Not implemented!"); + } + + private void WebHookServer_Send(object message) + { + throw new Exception("[API] WebHookServer_Send(): Not implemented!"); + } + #endregion +} \ No newline at end of file diff --git a/Runtime/Scripts/WorldAnalysisREST_Webhook.cs.meta b/Runtime/Scripts/WorldAnalysisREST_Webhook.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..b7ce0cd600b2b88adbe2859d4c659ddd924d1736 --- /dev/null +++ b/Runtime/Scripts/WorldAnalysisREST_Webhook.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 67d4b99a5f7593e4a857b6c88249d564 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Scripts/WorldAnalysisUnityHelper.cs b/Runtime/Scripts/WorldAnalysisUnityHelper.cs index b6f5b21805dbfb4d1023890eca2dd69465f7a570..830de284d346ca9fff7553343e2ccb965fabe1e2 100644 --- a/Runtime/Scripts/WorldAnalysisUnityHelper.cs +++ b/Runtime/Scripts/WorldAnalysisUnityHelper.cs @@ -33,7 +33,7 @@ public class WorldAnalysisUnityHelper /// /// the values to convert /// Converted Unity Matrix - public static Matrix4x4 ConvertETSIARFTransform3DToUnity(ETSI.ARF.OpenAPI.WorldStorage.Transform3D value) + public static Matrix4x4 ConvertETSIARFTransform3DToUnity(ETSI.ARF.OpenAPI.WorldAnalysis.Transform3D value) { if (value.Count == 16) {