From 0d6f170322fdc77ccff4c226595838bc649cfe02 Mon Sep 17 00:00:00 2001 From: Jerome Royan Date: Tue, 9 Nov 2021 11:24:38 +0100 Subject: [PATCH 01/29] Add branch policy documentation to the readme --- README.md | 15 +++++++++++++++ doc/images/branchingPolicy.png | Bin 0 -> 28961 bytes 2 files changed, 15 insertions(+) create mode 100644 doc/images/branchingPolicy.png diff --git a/README.md b/README.md index b335231..7a0c3f4 100644 --- a/README.md +++ b/README.md @@ -38,3 +38,18 @@ https://swagger.io/tools/swagger-codegen/ https://swagger.io/docs/open-source-tools/swagger-codegen/ +# Branching Policy +Distributed version control systems like Git offers developers great flexibility to share and manage code. But a branching policy is crucial to collaborate more easily while keeping track of releases with bug fixes. + +We consider 5 categories of branches: +- **develop**: collects the different features. While it is recommended that this branch be as stable as possible, each commit is not considered as a release, but much more as a pre-release. +- **feature**: dedicated to the development of features (named ***feature/*** *featureName*). These feature branches allow to share code among developers working on a common feature. When a feature is implemented, it must be tested before merging it to the develop branch with a pull request. When a feature branch is merged into develop, it must be suppress from the reposiory. It is recommended that the develop branch be merged into the feature branches on a regular basis to avoid any drift. +- **master**: corresponds to the last version of stable code. The develop branch is merged in the master branch when a release is ready. Bug fixes from release branches are also merged is the master branch when useful. +- **release**: dedicated to the releases. One branch per minor version release must be created (named ***release/*** *major_minor_patch*), and a tag must be set. When a bug is fixed on a release, it should be merge is the release branch. Then a new tag is created by increasing the patch digit of the release version. +- **bug**: dedicated to the bug fix of releases (named ***bug/*** *bugID*). + +Branching strategy + + + + diff --git a/doc/images/branchingPolicy.png b/doc/images/branchingPolicy.png new file mode 100644 index 0000000000000000000000000000000000000000..75597a218085e89d3a798c99497b080091f4e03c GIT binary patch literal 28961 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

kXA&XsSoi4?n#$vP66CD*`+`p(gRr0y8o~<$ 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 literal 0 HcmV?d00001 -- GitLab From a397c35546f0f95651ca98428ba2bcbc470722ef Mon Sep 17 00:00:00 2001 From: Nathan Chambron Date: Wed, 19 Jan 2022 11:01:40 +0100 Subject: [PATCH 02/29] added new API specs --- API/openapi.yaml | 218 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 218 insertions(+) create mode 100644 API/openapi.yaml diff --git a/API/openapi.yaml b/API/openapi.yaml new file mode 100644 index 0000000..b02cefa --- /dev/null +++ b/API/openapi.yaml @@ -0,0 +1,218 @@ +openapi: "3.0.0" +info: + version: 0.0.2 + title: World Storage API + description: API ensuring interoperability between an authoring tool and a World Storage service + license: + name: BSD-3-clause + url: https://opensource.org/licenses/BSD-3-Clause +servers: + - url: http://localhost:8080 +paths: + /ping: + get: + summary: Test the server availability + responses: + '200': + description: OK + /admin: + get: + summary: Get the version of the API + operationId: getVersion + responses: + '200': + description: OK world storage. + content: + text/plain: + schema: + type: string + /trackables: + post: + summary: Create a trackable + operationId: addTrackable + tags: + - trackables + requestBody: + description: the trackable to be added to the world storage + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/trackable' + application/xml: + schema: + $ref: '#/components/schemas/trackable' + responses: + '200': + description: OK returns the UUID of the Trackable defined by the world storage. + content: + text/plain: + schema: + type: string + '201': + description: Null response + default: + description: unexpected error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + delete: + summary: Deletes a trackable + operationId: deleteTrackable + tags: + - trackables + parameters: + - name: trackableId + in: path + description: trackable id to delete + required: true + schema: + type: string + responses: + '200': + description: OK + '400': + description: Invalid ID supplied + '404': + description: trackable not found + get: + summary: returns the list of all trackables defined by the world storage. + operationId: getTrackables + tags: + - trackables + responses: + 200: + description: OK returns all the Trackables defined by the world storage. + content: + application/json: + schema: + type : array + items : + $ref: "#/components/schemas/trackable" + 201: + description: Null response + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /trackables/{trackableId}: + get: + summary: Find a trackable by his ID + operationId: getTrackableById + tags: + - trackables + parameters: + - name: trackableId + in: path + description: ID of the trackable to retrieve + required: true + schema: + type: string + responses: + '200': + description: "successful operation" + content: + application/json: + schema: + $ref: '#/components/schemas/trackable' + '400': + description: "Invalid ID supplied" + '404': + description: "Trackable not found" +components: + schemas: + trackable: + type: object + required: + - creatorUID + - trackableType + - trackableEncodingInformation + - trackablePayload + - unitSystem + - trackableDimension + - keyvalueTagList + properties: + creatorUID: + description: A Universally Unique IDentifier identifying the creator of the trackable + type: string + format: uuid + example: c75f6324-77a0-11ec-90d6-0242ac120003 + trackableType: + description: Extensible list of trackable types possibly handled by complient World Storage implementation + type: string + enum: [FIDUCIAL_MARKER, IMAGE_MARKER, MAP, OTHER] + example: FIDUCIAL_MARKER + trackableEncodingInformation: + description: Identifies targeted framework and version of the format. + $ref: '#/components/schemas/encodingInformationStructure' + trackablePayload: + description: The data provided to create the trackable in a specific format handled by the World Storage service. + type: string + format: byte + example: "10110101" + localCRS: + description: Coordinate reference system of the trackable + type: array + minItems: 4 + maxItems: 4 + items: + type: array + items: + type: number + format: float + minItems: 4 + maxItems: 4 + example: [[-2, 1, -3, 4], + [4, 4, 4, 2], + [1, 0, -2, 1], + [-1, -2, 0, 0]] + unitSystem: + description: Unit of length + type: string + enum: [MM, CM, DM, M, DAM, HM, KM, INCH, FOOT, YARD, MILE] + example: M + trackableDimension: + description: Bounding box of the Trackable, {width, length, 0} for 2D trackables, {width, length, depth} for 3D trackables + type: array + items: + type: number + format: double + minItems: 3 + maxItems: 3 + example: [1,5,0] + keyvalueTagList: + description: List of additional parameters to be stored with the trackable. + type: object + additionalProperties: + type: array + items: + type: string + minItems: 1 + example: { "author" : ["james","donovan"], "image" : ["skater"]} + encodingInformationStructure: + required: + - dataFormat + - version + properties: + dataFormat: + description: Identifier of the target framework + type: string + enum: [HOLOLENS, ARKIT, ARCORE] + example : "HOLOLENS" + version: + description: The version of the format + type: string + example : "1.01" + Error: + required: + - code + - message + properties: + code: + type: integer + format: int32 + message: + type: string \ No newline at end of file -- GitLab From 1e65803a46b7e9703a748ea8e45600da2ecfae7a Mon Sep 17 00:00:00 2001 From: Nathan Chambron Date: Wed, 19 Jan 2022 17:15:06 +0100 Subject: [PATCH 03/29] modified deleteTrackable to give trackable id in path --- API/openapi.yaml | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/API/openapi.yaml b/API/openapi.yaml index b02cefa..e5093ec 100644 --- a/API/openapi.yaml +++ b/API/openapi.yaml @@ -57,25 +57,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - delete: - summary: Deletes a trackable - operationId: deleteTrackable - tags: - - trackables - parameters: - - name: trackableId - in: path - description: trackable id to delete - required: true - schema: - type: string - responses: - '200': - description: OK - '400': - description: Invalid ID supplied - '404': - description: trackable not found get: summary: returns the list of all trackables defined by the world storage. operationId: getTrackables @@ -121,7 +102,26 @@ paths: '400': description: "Invalid ID supplied" '404': - description: "Trackable not found" + description: "Trackable not found" + delete: + summary: Deletes a trackable + operationId: deleteTrackable + tags: + - trackables + parameters: + - name: trackableId + in: path + description: trackable id to delete + required: true + schema: + type: string + responses: + '200': + description: OK + '400': + description: Invalid ID supplied + '404': + description: trackable not found components: schemas: trackable: -- GitLab From fedbe058193f91a000aa7c3bdf2cefc3238be515 Mon Sep 17 00:00:00 2001 From: Nathan Chambron Date: Thu, 20 Jan 2022 17:33:19 +0100 Subject: [PATCH 04/29] modified param localCRS --- API/openapi.yaml | 22 +++++++++------------- API/openapitools.json | 7 +++++++ 2 files changed, 16 insertions(+), 13 deletions(-) create mode 100644 API/openapitools.json diff --git a/API/openapi.yaml b/API/openapi.yaml index e5093ec..7011bd0 100644 --- a/API/openapi.yaml +++ b/API/openapi.yaml @@ -154,21 +154,17 @@ components: format: byte example: "10110101" localCRS: - description: Coordinate reference system of the trackable + description: Coordinate reference system of the trackable, a 4*4 matrix (rowmajor) represented by a float vector type: array - minItems: 4 - maxItems: 4 + minItems: 16 + maxItems: 16 items: - type: array - items: - type: number - format: float - minItems: 4 - maxItems: 4 - example: [[-2, 1, -3, 4], - [4, 4, 4, 2], - [1, 0, -2, 1], - [-1, -2, 0, 0]] + type: number + format: float + example: [-2, 1, -3, 4, + 4, 4, 4, 2, + 1, 0, -2, 1, + -1, -2, 0, 0] unitSystem: description: Unit of length type: string diff --git a/API/openapitools.json b/API/openapitools.json new file mode 100644 index 0000000..3b40e47 --- /dev/null +++ b/API/openapitools.json @@ -0,0 +1,7 @@ +{ + "$schema": "node_modules/@openapitools/openapi-generator-cli/config.schema.json", + "spaces": 2, + "generator-cli": { + "version": "5.3.0" + } +} -- GitLab From 7180dd51e69448cd8e4a0d2f512d0be0a6b5f6c9 Mon Sep 17 00:00:00 2001 From: "BCOM\\nchambron" Date: Fri, 28 Jan 2022 17:01:26 +0100 Subject: [PATCH 05/29] add id attribute to Trackable schema --- API/openapi.yaml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/API/openapi.yaml b/API/openapi.yaml index 7011bd0..0428839 100644 --- a/API/openapi.yaml +++ b/API/openapi.yaml @@ -1,6 +1,6 @@ openapi: "3.0.0" info: - version: 0.0.2 + version: 0.0.3 title: World Storage API description: API ensuring interoperability between an authoring tool and a World Storage service license: @@ -132,9 +132,15 @@ components: - trackableEncodingInformation - trackablePayload - unitSystem + - localCRS - trackableDimension - keyvalueTagList properties: + id : + description: A Universally Unique IDentifier identifying the trackable + type: string + format: uuid + example: fa8bbe40-8052-11ec-a8a3-0242ac120002 creatorUID: description: A Universally Unique IDentifier identifying the creator of the trackable type: string -- GitLab From 45f9bada436e1fc9cd3d47b1fecd2f35703ace5c Mon Sep 17 00:00:00 2001 From: "BCOM\\nchambron" Date: Tue, 8 Feb 2022 15:34:12 +0100 Subject: [PATCH 06/29] renamed id to UUID --- API/openapi.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/API/openapi.yaml b/API/openapi.yaml index 0428839..600839b 100644 --- a/API/openapi.yaml +++ b/API/openapi.yaml @@ -127,6 +127,7 @@ components: trackable: type: object required: + - UID - creatorUID - trackableType - trackableEncodingInformation @@ -136,7 +137,7 @@ components: - trackableDimension - keyvalueTagList properties: - id : + UID: description: A Universally Unique IDentifier identifying the trackable type: string format: uuid -- GitLab From e4588e2390c93526d6af2c8bb533ad11c4246642 Mon Sep 17 00:00:00 2001 From: "BCOM\\nchambron" Date: Tue, 8 Feb 2022 15:40:29 +0100 Subject: [PATCH 07/29] renamed id to UUID/removed required --- API/openapi.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/API/openapi.yaml b/API/openapi.yaml index 600839b..8a0fad5 100644 --- a/API/openapi.yaml +++ b/API/openapi.yaml @@ -127,7 +127,6 @@ components: trackable: type: object required: - - UID - creatorUID - trackableType - trackableEncodingInformation -- GitLab From c9787960318ce0c1ea6d43deefcb20f6fee207ad Mon Sep 17 00:00:00 2001 From: Sylvain Renault Date: Wed, 16 Feb 2022 09:35:35 +0100 Subject: [PATCH 08/29] Fraunhofer use cases for dtwin --- .../DTWIN-SEQ-AR17-AddTrackable.png | Bin 0 -> 73869 bytes .../DTWIN-SEQ-AR17-AddTrackable.puml | 96 ++++++++++++++++++ UseCases/Fraunhofer HHI/DTWIN-UseCases.png | Bin 0 -> 78234 bytes UseCases/Fraunhofer HHI/DTWIN-UseCases.puml | 47 +++++++++ UseCases/Fraunhofer HHI/ReadMe.md | 5 + .../SEQ-DTWIN-SetupTrackables.puml | 75 ++++++++++++++ 6 files changed, 223 insertions(+) create mode 100644 UseCases/Fraunhofer HHI/DTWIN-SEQ-AR17-AddTrackable.png create mode 100644 UseCases/Fraunhofer HHI/DTWIN-SEQ-AR17-AddTrackable.puml create mode 100644 UseCases/Fraunhofer HHI/DTWIN-UseCases.png create mode 100644 UseCases/Fraunhofer HHI/DTWIN-UseCases.puml create mode 100644 UseCases/Fraunhofer HHI/ReadMe.md create mode 100644 UseCases/Fraunhofer HHI/SEQ-DTWIN-SetupTrackables.puml diff --git a/UseCases/Fraunhofer HHI/DTWIN-SEQ-AR17-AddTrackable.png b/UseCases/Fraunhofer HHI/DTWIN-SEQ-AR17-AddTrackable.png new file mode 100644 index 0000000000000000000000000000000000000000..3067079069622d2d763afa8873106c45d526675f GIT binary patch literal 73869 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 z WS : Extract features + + +alt successful case +rnote right WS +**Payload** + Unique Identifier +end rnote +WS -> AT: AR17-Trackable unique Identifier +deactivate WS +note right AT +Stores the identifier with the Trackable in the scene graph +end note +else ERROR: Trackable all exceptions +WS -> AT: AR17-Trackable return exception +end + +' THIS IS FOR SYSTEM B (Unity) +' ------------------------------- +WS <- AT: AR17-AddTrackable() - Unity (System B) + +rnote right AT +**Payload** + Creator UID (Unity Tag) ++ Trackable Type (image) ++ Trackable Encoding Information (Vuforia) ++ Trackable Payload (png image of Vuforia marker, size) ++ Local CRS (to the middle of the workbench) ++ Unit System (meters) ++ Trackable Scale ++ KeyValue Tag List (linked to HoloLens space mapping) +end rnote + +activate WS + +WS -> WS : Extract features + + +alt successful case +rnote right WS +**Payload** + Unique Identifier +end rnote +WS -> AT: AR17-Trackable unique Identifier +deactivate WS +note right AT +Stores the identifier with the Trackable in the scene graph +end note +else ERROR: Trackable all exceptions +WS -> AT: AR17-Trackable return exception +end + +rnote left AT +**Registrated Nodes** + QUESTION: + Is the 3d-pose (gridshell node) an object-trackable or a world anchor? + + **Payload** + Unique Identifier + + Type = Node + + CAD-Identifier + + CAD-Name + + 3DT Position + + Bounding Box + + Ref to Gizmos Objects (position/rotation gizmos) + + Ref to annonations (info label) + + Logistic State (intern) + + Montage Seq + + Ticket State (public) + +end rnote +@enduml diff --git a/UseCases/Fraunhofer HHI/DTWIN-UseCases.png b/UseCases/Fraunhofer HHI/DTWIN-UseCases.png new file mode 100644 index 0000000000000000000000000000000000000000..cb730ee25d44228ab1d2c4f9abab0ddb45f19351 GIT binary patch literal 78234 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%0DDOE1sS=UXZkCUsQ2#dj*S-E)R7JNEX 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�t*@a;NBrf=@4&E~aYcHv^ORhkE4J{y^{l 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 bX}(IMD?m_|Ws1HFPeHjlxqn&Z7)bjQjCYik literal 0 HcmV?d00001 diff --git a/UseCases/Fraunhofer HHI/DTWIN-UseCases.puml b/UseCases/Fraunhofer HHI/DTWIN-UseCases.puml new file mode 100644 index 0000000..e3025ba --- /dev/null +++ b/UseCases/Fraunhofer HHI/DTWIN-UseCases.puml @@ -0,0 +1,47 @@ +@startuml +'default +left to right direction + +rectangle "Authoring process" { + usecase "Login" as ucLOG + usecase "Setup Trackable" as ucST + usecase "Setup World Anchors" as ucSWA + usecase "Build AR Scene" as ucBARS + (ucST) -.> (ucLOG): <> + (ucSWA) -.> (ucLOG): <> + (ucBARS) -.> (ucLOG): <> + } + +package Users { + actor "Trackable Authoring" as TA + actor "World Anchor Authoring" as WAA + actor "AR Scene Authoring" as ASA +} + +package Services { + actor :Authentication Service: as AuS <> + actor :World Storage: as WS <> + actor :Asset Preparation: as AP <> + actor :Content Hosting: as CH <> +} + +'login +TA ---- (ucLOG) +WAA - (ucLOG) + +'setups +TA -- (ucST) +WAA -- (ucSWA) +ASA -- (ucBARS) + +'services +(ucLOG) ---- AuS +(ucST) -- WS +(ucST) -- AP +(ucSWA) -- WS +(ucSWA) -- AP +(ucBARS) -- CH +(ucBARS) -- WS +(ucBARS) -- AP + +@enduml \ No newline at end of file diff --git a/UseCases/Fraunhofer HHI/ReadMe.md b/UseCases/Fraunhofer HHI/ReadMe.md new file mode 100644 index 0000000..b850bbc --- /dev/null +++ b/UseCases/Fraunhofer HHI/ReadMe.md @@ -0,0 +1,5 @@ +# Fraunhofer HHI + +This is only for testing! + +Should be removed later. \ No newline at end of file diff --git a/UseCases/Fraunhofer HHI/SEQ-DTWIN-SetupTrackables.puml b/UseCases/Fraunhofer HHI/SEQ-DTWIN-SetupTrackables.puml new file mode 100644 index 0000000..fadc9d9 --- /dev/null +++ b/UseCases/Fraunhofer HHI/SEQ-DTWIN-SetupTrackables.puml @@ -0,0 +1,75 @@ +@startuml + +participant "World Storage" as WS +participant "Authoring Tool" as AT +participant "Trackable Author" as DS +participant "Asset Preparation" as AP +participant "Content Hosting" as CH +participant "Authentication Service" as AS + + +DS -> AS ++ : Login +return OK + +group Loop on 3D models +DS -> AP ++ : Request 3D Model of the World +return 3D Model (FBX) + +DS -> AT ++ : Load 3D Model into scene graph +return OK +end group + + +note right +Done by hand +end note + +group Loop on Trackables +DS -> AP ++ : Request Trackable +return Trackable + Description + +DS -> AT ++ : Place the Trackable in the scene graph +return OK + +DS -> AT ++ : Add Key/value tags on the Trackable +return OK +note right +Author level tags +end note + +end group +note right +Done by hand +end note + +group Loop on 3D models +DS -> AT ++ : Associate each 3D model to a Trackable +return OK +end group + +DS -> AT ++ : Press Save + +group Loop on Trackables +AT-> AT : Add Key/value tags on the Trackables (auto) +note right +Authoring application level tags (Author, date, location...) +end note + +AT -> WS ++ : AR17-AddTrackable +WS -> WS : Extract Feature +return Trackable ID + +AT-> AT : Store Trackable ID in the scene graph + +group Loop on associated models +AT -> WS ++ : AR17-AddModelToTrackable +return OK +end group +end group + +AT -> AT ++ : Save AR Project +return OK + +return OK + +@enduml -- GitLab From 54c578454ef3ac2b0c4294353f7512884e5eb052 Mon Sep 17 00:00:00 2001 From: Eric Villain Date: Thu, 17 Feb 2022 09:50:49 +0000 Subject: [PATCH 09/29] Update openapi.yaml --- API/openapi.yaml | 378 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 335 insertions(+), 43 deletions(-) diff --git a/API/openapi.yaml b/API/openapi.yaml index 8a0fad5..07fbb95 100644 --- a/API/openapi.yaml +++ b/API/openapi.yaml @@ -38,10 +38,10 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/trackable' + $ref: '#/components/schemas/Trackable' application/xml: schema: - $ref: '#/components/schemas/trackable' + $ref: '#/components/schemas/Trackable' responses: '200': description: OK returns the UUID of the Trackable defined by the world storage. @@ -70,7 +70,7 @@ paths: schema: type : array items : - $ref: "#/components/schemas/trackable" + $ref: "#/components/schemas/Trackable" 201: description: Null response default: @@ -78,7 +78,7 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/Error" + $ref: "#/components/schemas/Error" /trackables/{trackableId}: get: summary: Find a trackable by his ID @@ -94,15 +94,15 @@ paths: type: string responses: '200': - description: "successful operation" + description: Successful operation content: application/json: schema: - $ref: '#/components/schemas/trackable' + $ref: '#/components/schemas/Trackable' '400': - description: "Invalid ID supplied" + description: Invalid ID supplied '404': - description: "Trackable not found" + description: Trackable not found delete: summary: Deletes a trackable operationId: deleteTrackable @@ -122,17 +122,209 @@ paths: description: Invalid ID supplied '404': description: trackable not found + /worldAnchors: + post: + summary: Create a world anchor + operationId: addWorldAnchor + tags: + - world anchors + requestBody: + description: the world anchor to be added to the world storage + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/WorldAnchor' + application/xml: + schema: + $ref: '#/components/schemas/WorldAnchor' + responses: + '200': + description: OK returns the UUID of the World Anchor defined by the world storage. + content: + text/plain: + schema: + type: string + '201': + description: Null response + default: + description: unexpected error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + get: + summary: returns the list of all world anchors defined by the world storage. + operationId: getWorldAnchors + tags: + - world anchors + responses: + 200: + description: OK returns all the world anchors defined by the world storage. + content: + application/json: + schema: + type : array + items : + $ref: "#/components/schemas/WorldAnchor" + 201: + description: Null response + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /worldAnchors/{worldAnchorId}: + get: + summary: Find a world anchor by his ID + operationId: getWorldAnchorById + tags: + - world anchors + parameters: + - name: worldAnchorId + in: path + description: ID of the world anchor to retrieve + required: true + schema: + type: string + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/WorldAnchor' + '400': + description: Invalid ID supplied + '404': + description: World Anchor not found + delete: + summary: Deletes a world anchor + operationId: deleteWorldAnchor + tags: + - world anchors + parameters: + - name: worldAnchorId + in: path + description: world anchor id to delete + required: true + schema: + type: string + responses: + '200': + description: OK + '400': + description: Invalid ID supplied + '404': + description: World anchor not found + /worldLinks: + post: + summary: Create a link between world anchors and trackables + operationId: addWorldLink + tags: + - world links + requestBody: + description: the link to be added to the world storage + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/WorldLink' + application/xml: + schema: + $ref: '#/components/schemas/WorldLink' + responses: + '200': + description: OK returns the UUID of the link defined by the world storage. + content: + text/plain: + schema: + type: string + '201': + description: Null response + default: + description: unexpected error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + get: + summary: returns the list of all links defined by the world storage. + operationId: getWorldLinks + tags: + - world links + responses: + 200: + description: OK returns all the worldLinks defined by the world storage. + content: + application/json: + schema: + type : array + items : + $ref: "#/components/schemas/WorldLink" + 201: + description: Null response + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /worldLinks/{linkId}: + get: + summary: Find a link by his ID + operationId: getWorldLinkById + tags: + - world links + parameters: + - name: worldLinkId + in: path + description: ID of the link to retrieve + required: true + schema: + type: string + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/WorldLink' + '400': + description: Invalid ID supplied + '404': + description: World Link not found + delete: + summary: Deletes a worldLink + operationId: deleteWorldLink + tags: + - world links + parameters: + - name: linkId + in: path + description: link id to delete + required: true + schema: + type: string + responses: + '200': + description: OK + '400': + description: Invalid ID supplied + '404': + description: link not found components: schemas: - trackable: + Trackable: type: object required: - creatorUID - trackableType - trackableEncodingInformation - trackablePayload - - unitSystem - localCRS + - unit - trackableDimension - keyvalueTagList properties: @@ -153,48 +345,118 @@ components: example: FIDUCIAL_MARKER trackableEncodingInformation: description: Identifies targeted framework and version of the format. - $ref: '#/components/schemas/encodingInformationStructure' + $ref: '#/components/schemas/EncodingInformationStructure' trackablePayload: description: The data provided to create the trackable in a specific format handled by the World Storage service. type: string format: byte example: "10110101" localCRS: - description: Coordinate reference system of the trackable, a 4*4 matrix (rowmajor) represented by a float vector - type: array - minItems: 16 - maxItems: 16 - items: - type: number - format: float - example: [-2, 1, -3, 4, + description: Coordinate reference system + $ref: '#/components/schemas/CRS' + example: [-2, 1, -3, 4, 4, 4, 4, 2, 1, 0, -2, 1, -1, -2, 0, 0] - unitSystem: - description: Unit of length - type: string - enum: [MM, CM, DM, M, DAM, HM, KM, INCH, FOOT, YARD, MILE] - example: M + unit: + description: Unit of length + $ref: '#/components/schemas/UnitSystem' trackableDimension: - description: Bounding box of the Trackable, {width, length, 0} for 2D trackables, {width, length, depth} for 3D trackables - type: array - items: - type: number - format: double - minItems: 3 - maxItems: 3 - example: [1,5,0] - keyvalueTagList: - description: List of additional parameters to be stored with the trackable. - type: object - additionalProperties: - type: array - items: - type: string - minItems: 1 - example: { "author" : ["james","donovan"], "image" : ["skater"]} - encodingInformationStructure: + description: Bounding box of the Trackable, {width, length, 0} for 2D trackables, {width, length, depth} for 3D trackables + $ref: '#/components/schemas/Dimension' + example: [1,5,0] + keyvalueTags: + description: List of additional parameters to be stored + $ref: '#/components/schemas/KeyvalueTagList' + example: { "author" : ["james","donovan"], "image" : ["skater"]} + WorldAnchor: + type: object + required: + - creatorUID + - localCRS + - unit + - worldAnchorDimension + - keyvalueTagList + properties: + UID: + description: A Universally Unique IDentifier identifying the world anchor + type: string + format: uuid + example: ce8ccd80-56ee-2a5c-a8a3-0242ac150d002 + creatorUID: + description: A Universally Unique IDentifier identifying the creator of the world anchor + type: string + format: uuid + example: c75f6324-77a0-11ec-90d6-0242ac120003 + localCRS: + description: Coordinate reference system + $ref: '#/components/schemas/CRS' + example: [-2, 1, -3, 4, + 4, 4, 4, 2, + 1, 0, -2, 1, + -1, -2, 0, 0] + unit: + description: Unit of length + $ref: '#/components/schemas/UnitSystem' + worldAnchorDimension: + description: Bounding box {width, length, depth} + $ref: '#/components/schemas/Dimension' + example: [1,5,0] + keyvalueTags: + description: List of additional parameters to be stored + $ref: '#/components/schemas/KeyvalueTagList' + example: { "Place" : ["Museum 1"], "room" : ["B4"]} + WorldLink: + type: object + required: + - creatorUID + - UIDA + - UIDB + - localCRS + - unit + - linkDimension + - keyvalueTags + properties: + UID: + description: A Universally Unique IDentifier identifying the link + type: string + format: uuid + example: ce8ccd80-56ee-2a5c-a8a3-0242ac150d002 + creatorUID: + description: A Universally Unique IDentifier identifying the creator of the link + type: string + format: uuid + example: c75f6324-77a0-11ec-90d6-0242ac120003 + UIDA: + description: A Universally Unique IDentifier identifying a world anchor or trackable + type: string + format: uuid + example: ce8ccd80-56ee-2a5c-a8a3-0242ac150d002 + UIDB: + description: A Universally Unique IDentifier identifying a world anchor or trackable + type: string + format: uuid + example: ce8ccd80-56ee-2a5c-a8a3-0242ac150d002 + localCRS: + description: Coordinate reference system + $ref: '#/components/schemas/CRS' + example: [-2, 1, -3, 4, + 4, 4, 4, 2, + 1, 0, -2, 1, + -1, -2, 0, 0] + unit: + description: Unit of length + $ref: '#/components/schemas/UnitSystem' + example: M + linkDimension: + description: Bounding box + $ref: '#/components/schemas/Dimension' + example: [1,5,0] + keyvalueTags: + description: List of additional parameters to be stored + $ref: '#/components/schemas/KeyvalueTagList' + example: { "LinkType" : ["Hierarchy"]} + EncodingInformationStructure: required: - dataFormat - version @@ -208,6 +470,36 @@ components: description: The version of the format type: string example : "1.01" + CRS: + description: Coordinate reference system of the world anchor, a 4*4 matrix (rowmajor) represented by a float vector + type: array + minItems: 16 + maxItems: 16 + items: + type: number + format: float + UnitSystem: + description: Unit of length + type: string + enum: [MM, CM, DM, M, DAM, HM, KM, INCH, FOOT, YARD, MILE] + Dimension: + description: Bounding box {width, length, depth} + type: array + items: + type: number + format: double + minItems: 3 + maxItems: 3 + example: [1,5,0] + KeyvalueTagList: + description: List of additional parameters to be stored with the trackable. + type: object + additionalProperties: + type: array + items: + type: string + minItems: 1 + example: { "Place" : ["Museum 1"], "room" : ["B4"]} Error: required: - code @@ -217,4 +509,4 @@ components: type: integer format: int32 message: - type: string \ No newline at end of file + type: string -- GitLab From eec9df4cfa3159f67476a87fd7dfc47a5800fe00 Mon Sep 17 00:00:00 2001 From: Eric Villain Date: Wed, 23 Feb 2022 16:31:40 +0000 Subject: [PATCH 10/29] Replace Uid and id by UUID where it's necessary Dimension becomes size Create an orientation for the world link (UUIDFrom, UUIDTo) CRS becomesTransform3D Deleted every duplicated descriptions (they are factorized at the schemas level when possible to avoid discrepancies) --- API/openapi.yaml | 149 ++++++++++++++++++++--------------------------- 1 file changed, 64 insertions(+), 85 deletions(-) diff --git a/API/openapi.yaml b/API/openapi.yaml index 07fbb95..93dec27 100644 --- a/API/openapi.yaml +++ b/API/openapi.yaml @@ -1,6 +1,6 @@ openapi: "3.0.0" info: - version: 0.0.3 + version: 0.0.4 title: World Storage API description: API ensuring interoperability between an authoring tool and a World Storage service license: @@ -57,13 +57,16 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' +# Check 2xx, 4xx, 5xx... + '401': + $ref: '#/components/responses/UUID' get: summary: returns the list of all trackables defined by the world storage. operationId: getTrackables tags: - trackables responses: - 200: + '200': description: OK returns all the Trackables defined by the world storage. content: application/json: @@ -71,7 +74,7 @@ paths: type : array items : $ref: "#/components/schemas/Trackable" - 201: + '201': description: Null response default: description: unexpected error @@ -79,16 +82,17 @@ paths: application/json: schema: $ref: "#/components/schemas/Error" - /trackables/{trackableId}: + + /trackables/{trackableUUID}: get: - summary: Find a trackable by his ID + summary: Find a trackable by its UUID operationId: getTrackableById tags: - trackables parameters: - - name: trackableId + - name: trackableUUID in: path - description: ID of the trackable to retrieve + description: UUID of the trackable to retrieve required: true schema: type: string @@ -100,7 +104,7 @@ paths: schema: $ref: '#/components/schemas/Trackable' '400': - description: Invalid ID supplied + description: Invalid UUID supplied '404': description: Trackable not found delete: @@ -109,9 +113,9 @@ paths: tags: - trackables parameters: - - name: trackableId + - name: trackableUUID in: path - description: trackable id to delete + description: trackable UUID to delete required: true schema: type: string @@ -119,7 +123,7 @@ paths: '200': description: OK '400': - description: Invalid ID supplied + description: Invalid UUID supplied '404': description: trackable not found /worldAnchors: @@ -175,16 +179,16 @@ paths: application/json: schema: $ref: "#/components/schemas/Error" - /worldAnchors/{worldAnchorId}: + /worldAnchors/{worldAnchorUUID}: get: - summary: Find a world anchor by his ID + summary: Find a world anchor by his UUID operationId: getWorldAnchorById tags: - world anchors parameters: - - name: worldAnchorId + - name: trackableUUID in: path - description: ID of the world anchor to retrieve + description: UUID of the world anchor to retrieve required: true schema: type: string @@ -196,7 +200,7 @@ paths: schema: $ref: '#/components/schemas/WorldAnchor' '400': - description: Invalid ID supplied + description: Invalid UUID supplied '404': description: World Anchor not found delete: @@ -205,9 +209,9 @@ paths: tags: - world anchors parameters: - - name: worldAnchorId + - name: trackableUUID in: path - description: world anchor id to delete + description: world anchor UUID to delete required: true schema: type: string @@ -215,7 +219,7 @@ paths: '200': description: OK '400': - description: Invalid ID supplied + description: Invalid UUID supplied '404': description: World anchor not found /worldLinks: @@ -271,14 +275,14 @@ paths: application/json: schema: $ref: "#/components/schemas/Error" - /worldLinks/{linkId}: + /worldLinks/{worldLinkUUID}: get: summary: Find a link by his ID operationId: getWorldLinkById tags: - world links parameters: - - name: worldLinkId + - name: worldLinkUUID in: path description: ID of the link to retrieve required: true @@ -301,7 +305,7 @@ paths: tags: - world links parameters: - - name: linkId + - name: worldLinkUUID in: path description: link id to delete required: true @@ -319,22 +323,22 @@ components: Trackable: type: object required: - - creatorUID + - creatorUUID - trackableType - trackableEncodingInformation - trackablePayload - localCRS - unit - - trackableDimension + - trackableSize - keyvalueTagList properties: - UID: - description: A Universally Unique IDentifier identifying the trackable + UUID: + description: A Universally Unique IDentifier identifying the trackable (RFC 4122) type: string format: uuid example: fa8bbe40-8052-11ec-a8a3-0242ac120002 - creatorUID: - description: A Universally Unique IDentifier identifying the creator of the trackable + creatorUUID: + description: A Universally Unique IDentifier identifying the creator of the trackable (a person, a team or a company) type: string format: uuid example: c75f6324-77a0-11ec-90d6-0242ac120003 @@ -344,7 +348,6 @@ components: enum: [FIDUCIAL_MARKER, IMAGE_MARKER, MAP, OTHER] example: FIDUCIAL_MARKER trackableEncodingInformation: - description: Identifies targeted framework and version of the format. $ref: '#/components/schemas/EncodingInformationStructure' trackablePayload: description: The data provided to create the trackable in a specific format handled by the World Storage service. @@ -352,106 +355,77 @@ components: format: byte example: "10110101" localCRS: - description: Coordinate reference system - $ref: '#/components/schemas/CRS' - example: [-2, 1, -3, 4, - 4, 4, 4, 2, - 1, 0, -2, 1, - -1, -2, 0, 0] + $ref: '#/components/schemas/Transform3D' unit: - description: Unit of length $ref: '#/components/schemas/UnitSystem' - trackableDimension: - description: Bounding box of the Trackable, {width, length, 0} for 2D trackables, {width, length, depth} for 3D trackables - $ref: '#/components/schemas/Dimension' - example: [1,5,0] + trackableSize: + $ref: '#/components/schemas/Size' keyvalueTags: - description: List of additional parameters to be stored $ref: '#/components/schemas/KeyvalueTagList' - example: { "author" : ["james","donovan"], "image" : ["skater"]} - WorldAnchor: + WorldAnchor: type: object required: - - creatorUID + - creatorUUID - localCRS - unit - - worldAnchorDimension + - worldAnchorSize - keyvalueTagList properties: - UID: + UUID: description: A Universally Unique IDentifier identifying the world anchor type: string format: uuid example: ce8ccd80-56ee-2a5c-a8a3-0242ac150d002 - creatorUID: + creatorUUID: description: A Universally Unique IDentifier identifying the creator of the world anchor type: string format: uuid example: c75f6324-77a0-11ec-90d6-0242ac120003 localCRS: - description: Coordinate reference system - $ref: '#/components/schemas/CRS' - example: [-2, 1, -3, 4, - 4, 4, 4, 2, - 1, 0, -2, 1, - -1, -2, 0, 0] + $ref: '#/components/schemas/Transform3D' unit: - description: Unit of length $ref: '#/components/schemas/UnitSystem' - worldAnchorDimension: - description: Bounding box {width, length, depth} - $ref: '#/components/schemas/Dimension' - example: [1,5,0] + worldAnchorSize: + $ref: '#/components/schemas/Size' keyvalueTags: - description: List of additional parameters to be stored $ref: '#/components/schemas/KeyvalueTagList' - example: { "Place" : ["Museum 1"], "room" : ["B4"]} WorldLink: type: object required: - - creatorUID - - UIDA - - UIDB - - localCRS + - creatorUUID + - UUIDFrom + - UUIDTo + - transform - unit - - linkDimension + - linkSize - keyvalueTags properties: - UID: + UUID: description: A Universally Unique IDentifier identifying the link type: string format: uuid example: ce8ccd80-56ee-2a5c-a8a3-0242ac150d002 - creatorUID: + creatorUUID: description: A Universally Unique IDentifier identifying the creator of the link type: string format: uuid example: c75f6324-77a0-11ec-90d6-0242ac120003 - UIDA: + UUIDFrom: description: A Universally Unique IDentifier identifying a world anchor or trackable type: string format: uuid example: ce8ccd80-56ee-2a5c-a8a3-0242ac150d002 - UIDB: + UUIDTo: description: A Universally Unique IDentifier identifying a world anchor or trackable type: string format: uuid example: ce8ccd80-56ee-2a5c-a8a3-0242ac150d002 - localCRS: - description: Coordinate reference system - $ref: '#/components/schemas/CRS' - example: [-2, 1, -3, 4, - 4, 4, 4, 2, - 1, 0, -2, 1, - -1, -2, 0, 0] + transform: + $ref: '#/components/schemas/Transform3D' unit: - description: Unit of length $ref: '#/components/schemas/UnitSystem' - example: M - linkDimension: - description: Bounding box - $ref: '#/components/schemas/Dimension' - example: [1,5,0] + linkSize: + $ref: '#/components/schemas/Size' keyvalueTags: description: List of additional parameters to be stored $ref: '#/components/schemas/KeyvalueTagList' @@ -470,7 +444,7 @@ components: description: The version of the format type: string example : "1.01" - CRS: + Transform3D: description: Coordinate reference system of the world anchor, a 4*4 matrix (rowmajor) represented by a float vector type: array minItems: 16 @@ -478,12 +452,17 @@ components: items: type: number format: float + example: [-2, 1,-3, 4, + 4, 4, 4, 2, + 1, 0,-2, 1, + -1,-2, 0, 0] UnitSystem: description: Unit of length type: string enum: [MM, CM, DM, M, DAM, HM, KM, INCH, FOOT, YARD, MILE] - Dimension: - description: Bounding box {width, length, depth} + example: M + Size: + description: Size {width, length, depth} type: array items: type: number -- GitLab From 3b4ea60682b4ffedc2bce100220cc196075d8cef Mon Sep 17 00:00:00 2001 From: Eric Villain Date: Wed, 23 Feb 2022 16:34:27 +0000 Subject: [PATCH 11/29] Correction of an indentation mistake --- API/openapi.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/API/openapi.yaml b/API/openapi.yaml index 93dec27..fa69aa7 100644 --- a/API/openapi.yaml +++ b/API/openapi.yaml @@ -362,7 +362,7 @@ components: $ref: '#/components/schemas/Size' keyvalueTags: $ref: '#/components/schemas/KeyvalueTagList' - WorldAnchor: + WorldAnchor: type: object required: - creatorUUID -- GitLab From 6d3f113c4e1a28df86c79ed46990483a55991149 Mon Sep 17 00:00:00 2001 From: Sylvain Renault Date: Fri, 4 Mar 2022 17:45:11 +0100 Subject: [PATCH 12/29] Major and minor changes. New headlines in yaml file. Reformating whoel yaml. Introduction of components/repsonses params. Some extensions in two MD files. New GET method for the end objects of a world link. --- API/openapi.yaml | 363 +++++++++++++++++++++++++++++++++-------------- README.md | 35 +++-- 2 files changed, 282 insertions(+), 116 deletions(-) diff --git a/API/openapi.yaml b/API/openapi.yaml index fa69aa7..5186d81 100644 --- a/API/openapi.yaml +++ b/API/openapi.yaml @@ -1,4 +1,17 @@ openapi: "3.0.0" +# +# API for the Augmented Reality Framework (ARF) +# Working group: ETSI ISG ARF +# STF group: STF620 (validation) +# (C) ETSI - 2022 +# +# References: +# - Explaination UUID: https://en.wikipedia.org/wiki/Universally_unique_identifier / https://fr.wikipedia.org/wiki/Universally_unique_identifier +# - UUID formats: 8-4-4-4-12 format string, lower case (but case insensitive on input) +# - UUID RFC4122: https://datatracker.ietf.org/doc/html/rfc4122#section-3 +# - Rules for RESTful error code RFC2616: https://datatracker.ietf.org/doc/html/rfc2616#section-10 +# - Guide: https://restfulapi.net/http-status-codes/ +# info: version: 0.0.4 title: World Storage API @@ -14,26 +27,30 @@ paths: summary: Test the server availability responses: '200': - description: OK + description: OK, world storage alive. /admin: get: - summary: Get the version of the API + summary: Get the version of the API. operationId: getVersion responses: '200': - description: OK world storage. + description: OK, world storage ready. content: text/plain: schema: - type: string + type: string + +############## +# TRACKABLES # +############## /trackables: post: - summary: Create a trackable + summary: Create a trackable. operationId: addTrackable tags: - trackables requestBody: - description: the trackable to be added to the world storage + description: The trackable to be added to the world storage. required: true content: application/json: @@ -44,30 +61,27 @@ paths: $ref: '#/components/schemas/Trackable' responses: '200': - description: OK returns the UUID of the Trackable defined by the world storage. + description: OK, returns the UUID of the Trackable defined by the world storage. content: text/plain: schema: type: string '201': - description: Null response - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' -# Check 2xx, 4xx, 5xx... - '401': - $ref: '#/components/responses/UUID' + description: Null response. + '400': + $ref: '#/components/responses/400_BadRequest' + '409': + $ref: '#/components/responses/409_NotEmptyUUID' + 'default': + $ref: '#/components/responses/4xx_UnexpectedError' get: - summary: returns the list of all trackables defined by the world storage. + summary: Returns the list of all trackables defined by the world storage. operationId: getTrackables tags: - trackables responses: '200': - description: OK returns all the Trackables defined by the world storage. + description: OK, returns all the Trackables defined by the world storage. content: application/json: schema: @@ -75,65 +89,67 @@ paths: items : $ref: "#/components/schemas/Trackable" '201': - description: Null response + description: Null response. default: - description: unexpected error - content: - application/json: - schema: - $ref: "#/components/schemas/Error" + $ref: '#/components/responses/4xx_UnexpectedError' /trackables/{trackableUUID}: get: - summary: Find a trackable by its UUID + summary: Find a trackable by its UUID. operationId: getTrackableById tags: - trackables parameters: - name: trackableUUID in: path - description: UUID of the trackable to retrieve + description: UUID of the trackable to retrieve. required: true schema: type: string + format: uuid responses: '200': - description: Successful operation + description: Successful operation. content: application/json: schema: $ref: '#/components/schemas/Trackable' '400': - description: Invalid UUID supplied + $ref: '#/components/responses/400_InvalidUUID' '404': - description: Trackable not found + $ref: '#/components/responses/404_NotFoundUUID' delete: - summary: Deletes a trackable + summary: Deletes a trackable. operationId: deleteTrackable tags: - trackables parameters: - name: trackableUUID in: path - description: trackable UUID to delete + description: Trackable UUID to delete. required: true schema: type: string + format: uuid responses: '200': - description: OK + description: OK, delete successful. '400': - description: Invalid UUID supplied + $ref: '#/components/responses/400_InvalidUUID' '404': - description: trackable not found + $ref: '#/components/responses/404_NotFoundUUID' + +################# +# WORLD ANCHORS # +################# /worldAnchors: post: - summary: Create a world anchor + summary: Create a world anchor. operationId: addWorldAnchor tags: - world anchors requestBody: - description: the world anchor to be added to the world storage + description: The world anchor to be added to the world storage. required: true content: application/json: @@ -144,92 +160,95 @@ paths: $ref: '#/components/schemas/WorldAnchor' responses: '200': - description: OK returns the UUID of the World Anchor defined by the world storage. + description: OK, returns the UUID of the World Anchor defined by the world storage. content: text/plain: schema: type: string '201': - description: Null response - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' + description: Null response. + '400': + $ref: '#/components/responses/400_BadRequest' + '409': + $ref: '#/components/responses/409_NotEmptyUUID' + 'default': + $ref: '#/components/responses/4xx_UnexpectedError' get: - summary: returns the list of all world anchors defined by the world storage. + summary: Returns the list of all world anchors defined by the world storage. operationId: getWorldAnchors tags: - world anchors responses: - 200: - description: OK returns all the world anchors defined by the world storage. + '200': + description: OK, returns all the world anchors defined by the world storage. content: application/json: schema: type : array items : $ref: "#/components/schemas/WorldAnchor" - 201: - description: Null response + '201': + description: Null response. default: - description: unexpected error - content: - application/json: - schema: - $ref: "#/components/schemas/Error" + $ref: '#/components/responses/4xx_UnexpectedError' + /worldAnchors/{worldAnchorUUID}: get: - summary: Find a world anchor by his UUID + summary: Find a world anchor by its UUID. operationId: getWorldAnchorById tags: - world anchors parameters: - - name: trackableUUID + - name: worldAnchorUUID in: path - description: UUID of the world anchor to retrieve + description: UUID of the world anchor to retrieve. required: true schema: type: string + format: uuid responses: '200': - description: Successful operation + description: Successful operation. content: application/json: schema: $ref: '#/components/schemas/WorldAnchor' '400': - description: Invalid UUID supplied + $ref: '#/components/responses/400_InvalidUUID' '404': - description: World Anchor not found + $ref: '#/components/responses/404_NotFoundUUID' delete: - summary: Deletes a world anchor + summary: Deletes a world anchor. operationId: deleteWorldAnchor tags: - world anchors parameters: - - name: trackableUUID + - name: worldAnchorUUID in: path - description: world anchor UUID to delete + description: World anchor UUID to delete. required: true schema: type: string + format: uuid responses: '200': - description: OK + description: OK, delete successful. '400': - description: Invalid UUID supplied + $ref: '#/components/responses/400_InvalidUUID' '404': - description: World anchor not found + $ref: '#/components/responses/404_NotFoundUUID' + +############### +# WORLD LINKS # +############### /worldLinks: post: - summary: Create a link between world anchors and trackables + summary: Create a link between world anchors and trackables. operationId: addWorldLink tags: - world links requestBody: - description: the link to be added to the world storage + description: The link to be added to the world storage. required: true content: application/json: @@ -240,26 +259,26 @@ paths: $ref: '#/components/schemas/WorldLink' responses: '200': - description: OK returns the UUID of the link defined by the world storage. + description: OK, returns the UUID of the link defined by the world storage. content: text/plain: schema: type: string '201': description: Null response - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' + '400': + $ref: '#/components/responses/400_BadRequest' + '409': + $ref: '#/components/responses/409_NotEmptyUUID' + 'default': + $ref: '#/components/responses/4xx_UnexpectedError' get: - summary: returns the list of all links defined by the world storage. + summary: Returns the list of all links defined by the world storage. operationId: getWorldLinks tags: - world links responses: - 200: + '200': description: OK returns all the worldLinks defined by the world storage. content: application/json: @@ -267,40 +286,38 @@ paths: type : array items : $ref: "#/components/schemas/WorldLink" - 201: + '201': description: Null response default: - description: unexpected error - content: - application/json: - schema: - $ref: "#/components/schemas/Error" + $ref: '#/components/responses/4xx_UnexpectedError' + /worldLinks/{worldLinkUUID}: get: - summary: Find a link by his ID + summary: Find a link by its UUID. operationId: getWorldLinkById tags: - world links parameters: - name: worldLinkUUID in: path - description: ID of the link to retrieve + description: UUID of the link to retrieve. required: true schema: type: string + format: uuid responses: '200': - description: Successful operation + description: Successful operation. content: application/json: schema: $ref: '#/components/schemas/WorldLink' '400': - description: Invalid ID supplied + $ref: '#/components/responses/400_InvalidUUID' '404': - description: World Link not found + $ref: '#/components/responses/404_NotFoundUUID' delete: - summary: Deletes a worldLink + summary: Deletes a worldLink. operationId: deleteWorldLink tags: - world links @@ -311,14 +328,60 @@ paths: required: true schema: type: string + format: uuid responses: '200': description: OK '400': - description: Invalid ID supplied + $ref: '#/components/responses/400_InvalidUUID' + '404': + $ref: '#/components/responses/404_NotFoundUUID' + + /worldLinks/attached/{worldLinkUUID}: + get: + summary: Retrieve end objects connected to this world link by its UUID. + operationId: getAttachedObjectsFromUUID + tags: + - world links + parameters: + - name: worldLinkUUID + in: path + description: UUID of the link from which you will retrieve the end objects. + required: true + schema: + type: string + format: uuid + responses: + '200': + description: Successful operation. + content: + application/json: + schema: + $ref: '#/components/schemas/AttachedObjects' + '400': + $ref: '#/components/responses/400_InvalidUUID' '404': - description: link not found + $ref: '#/components/responses/404_NotFoundUUID' + +# COMPONENTS ############################################### components: + #------------------------------- + # Reusable operation parameters + #------------------------------- + parameters: + UUIDParams: + name: UUID + in: path + required: true + description: A Universally Unique IDentifier identifying the object + schema: + type: string + format: uuid + default: "00000000-0000-0000-0000-000000000000" + + #------------------------------- + # Reusable schemas (data models) + #------------------------------- schemas: Trackable: type: object @@ -333,17 +396,17 @@ components: - keyvalueTagList properties: UUID: - description: A Universally Unique IDentifier identifying the trackable (RFC 4122) + description: A Universally Unique IDentifier identifying the trackable (RFC 4122). type: string format: uuid example: fa8bbe40-8052-11ec-a8a3-0242ac120002 creatorUUID: - description: A Universally Unique IDentifier identifying the creator of the trackable (a person, a team or a company) + description: A Universally Unique IDentifier identifying the creator of the trackable (a person, a team or a company). type: string format: uuid example: c75f6324-77a0-11ec-90d6-0242ac120003 trackableType: - description: Extensible list of trackable types possibly handled by complient World Storage implementation + description: Extensible list of trackable types possibly handled by complient World Storage implementation. type: string enum: [FIDUCIAL_MARKER, IMAGE_MARKER, MAP, OTHER] example: FIDUCIAL_MARKER @@ -362,6 +425,7 @@ components: $ref: '#/components/schemas/Size' keyvalueTags: $ref: '#/components/schemas/KeyvalueTagList' + WorldAnchor: type: object required: @@ -372,12 +436,12 @@ components: - keyvalueTagList properties: UUID: - description: A Universally Unique IDentifier identifying the world anchor + description: A Universally Unique IDentifier identifying the world anchor (RFC 4122). type: string format: uuid example: ce8ccd80-56ee-2a5c-a8a3-0242ac150d002 creatorUUID: - description: A Universally Unique IDentifier identifying the creator of the world anchor + description: A Universally Unique IDentifier identifying the creator of the world anchor. type: string format: uuid example: c75f6324-77a0-11ec-90d6-0242ac120003 @@ -389,6 +453,7 @@ components: $ref: '#/components/schemas/Size' keyvalueTags: $ref: '#/components/schemas/KeyvalueTagList' + WorldLink: type: object required: @@ -401,22 +466,22 @@ components: - keyvalueTags properties: UUID: - description: A Universally Unique IDentifier identifying the link + description: A Universally Unique IDentifier identifying the link (RFC 4122). type: string format: uuid example: ce8ccd80-56ee-2a5c-a8a3-0242ac150d002 creatorUUID: - description: A Universally Unique IDentifier identifying the creator of the link + description: A Universally Unique IDentifier identifying the creator of the link. type: string format: uuid example: c75f6324-77a0-11ec-90d6-0242ac120003 UUIDFrom: - description: A Universally Unique IDentifier identifying a world anchor or trackable + description: A Universally Unique IDentifier identifying a world anchor or trackable. type: string format: uuid example: ce8ccd80-56ee-2a5c-a8a3-0242ac150d002 UUIDTo: - description: A Universally Unique IDentifier identifying a world anchor or trackable + description: A Universally Unique IDentifier identifying a world anchor or trackable. type: string format: uuid example: ce8ccd80-56ee-2a5c-a8a3-0242ac150d002 @@ -429,7 +494,37 @@ components: keyvalueTags: description: List of additional parameters to be stored $ref: '#/components/schemas/KeyvalueTagList' - example: { "LinkType" : ["Hierarchy"]} + example: { "LinkType" : ["Hierarchy"]} + + AttachedObjects: + type: object + required: + - UUID + - UUIDFrom + - UUIDTo + - TypeFrom + - TypeTo + properties: + UUID: + description: A Universally Unique IDentifier identifying the link. + type: string + format: uuid + example: ce8ccd80-56ee-2a5c-a8a3-0242ac150d002 + UUIDFrom: + description: A Universally Unique IDentifier identifying a world anchor or trackable. + type: string + format: uuid + example: ce8ccd80-56ee-2a5c-a8a3-0242ac150d002 + UUIDTo: + description: A Universally Unique IDentifier identifying a world anchor or trackable. + type: string + format: uuid + example: ce8ccd80-56ee-2a5c-a8a3-0242ac150d002 + TypeFrom: + $ref: '#/components/schemas/ObjectType' + TypeTo: + $ref: '#/components/schemas/ObjectType' + EncodingInformationStructure: required: - dataFormat @@ -444,6 +539,7 @@ components: description: The version of the format type: string example : "1.01" + Transform3D: description: Coordinate reference system of the world anchor, a 4*4 matrix (rowmajor) represented by a float vector type: array @@ -456,20 +552,29 @@ components: 4, 4, 4, 2, 1, 0,-2, 1, -1,-2, 0, 0] + + ObjectType: + description: Type of an world representaion object. + type: string + enum: [Trackable, WorldAnchor, WorldLink] + example: Trackable + UnitSystem: - description: Unit of length + description: Unit of length. type: string enum: [MM, CM, DM, M, DAM, HM, KM, INCH, FOOT, YARD, MILE] example: M + Size: - description: Size {width, length, depth} + description: Size {width, length, depth}. type: array items: type: number format: double minItems: 3 maxItems: 3 - example: [1,5,0] + example: [1,5,0] + KeyvalueTagList: description: List of additional parameters to be stored with the trackable. type: object @@ -479,6 +584,7 @@ components: type: string minItems: 1 example: { "Place" : ["Museum 1"], "room" : ["B4"]} + Error: required: - code @@ -489,3 +595,50 @@ components: format: int32 message: type: string + #------------------------------- + # Reusable responses + #------------------------------- + responses: + ####################### + # 1xx : Informational # + ####################### + + ################# + # 2xx : Success # + ################# + + ##################### + # 3xx : Redirection # + ##################### + + ####################### + # 4xx : Client Errors # + ####################### + 400_BadRequest: + description: Bad request. + + 400_InvalidUUID: + description: Invalid UUID supplied. + + 404_NotFoundUUID: + description: Not found, could not find UUID in database. + + 409_NotEmptyUUID: + description: Invalid UUID, id must be a Nil value. + + 4xx_UnexpectedError: # Can be referenced as '#/components/responses/GenericError' + description: Unexpected error. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + ######################## + # 5xx : Server Errors # + ######################## + 5xx_UnexpectedError: + description: Unexpected server error. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' diff --git a/README.md b/README.md index 51e23fc..a45f4c5 100644 --- a/README.md +++ b/README.md @@ -97,24 +97,37 @@ Contains temporary office documents that are edited collaboratively and all othe - Visual Studio - Visual Studio Code -- Unity 3D +- Unity 3D (Version 2020.3 LTS) -# Branching Policy -Distributed version control systems like Git offers developers great flexibility to share and manage code. But a branching policy is crucial to collaborate more easily while keeping track of releases with bug fixes. +# Creating Server/Client Code -We consider 5 categories of branches: -- **develop**: collects the different features. While it is recommended that this branch be as stable as possible, each commit is not considered as a release, but much more as a pre-release. -- **feature**: dedicated to the development of features (named ***feature/*** *featureName*). These feature branches allow to share code among developers working on a common feature. When a feature is implemented, it must be tested before merging it to the develop branch with a pull request. When a feature branch is merged into develop, it must be suppress from the reposiory. It is recommended that the develop branch be merged into the feature branches on a regular basis to avoid any drift. -- **master**: corresponds to the last version of stable code. The develop branch is merged in the master branch when a release is ready. Bug fixes from release branches are also merged is the master branch when useful. -- **release**: dedicated to the releases. One branch per minor version release must be created (named ***release/*** *major_minor_patch*), and a tag must be set. When a bug is fixed on a release, it should be merge is the release branch. Then a new tag is created by increasing the patch digit of the release version. -- **bug**: dedicated to the bug fix of releases (named ***bug/*** *bugID*). +## Tool: openapi-generator -Branching strategy +We recommand the usage of the open source command-line tool **openapi-generator** while it has a good compatibility to API v3.x and produces accurate source code, similar to Swagger. +Find a description here: https://openapi-generator.tech/docs/usage/ +Install the tool with "npm", see: https://openapi-generator.tech/docs/installation/ +### Help +> npx @openapitools/openapi-generator-cli help +### Validating the api + +> npx @openapitools/openapi-generator-cli validate -i .\openapi.yaml + +### Example C++ Server (Pistache) + +> npx @openapitools/openapi-generator-cli generate -i openapi.yaml -g cpp-pistache-server -o ./codeGeneration/sever/cpp/pistache + +### Example ASP.NET Server (C#) + +> npx @openapi-generator-cli generate -i openapi.yaml -g aspnetcore -o ./codeGeneration/server/aspnetcore + +### Example C# Client + +> npx @openapitools/openapi-generator-cli generate -i openapi.yaml -g csharp-netcore -o ./codeGeneration/client/c#/netcore # Branching Policy Distributed version control systems like Git offers developers great flexibility to share and manage code. But a branching policy is crucial to collaborate more easily while keeping track of releases with bug fixes. @@ -126,7 +139,7 @@ We consider 5 categories of branches: - **release**: dedicated to the releases. One branch per minor version release must be created (named ***release/*** *major_minor_patch*), and a tag must be set. When a bug is fixed on a release, it should be merge is the release branch. Then a new tag is created by increasing the patch digit of the release version. - **bug**: dedicated to the bug fix of releases (named ***bug/*** *bugID*). -Branching strategy +Branching strategy -- GitLab From 322e9997607e5ea9583cad3b3b359a6730be1159 Mon Sep 17 00:00:00 2001 From: Sylvain Renault Date: Fri, 4 Mar 2022 18:26:22 +0100 Subject: [PATCH 13/29] Referecing new components/responses params. Some corrections in the main MD file. Commenting "application/xml" block while this create some warnings in the generator. --- API/openapi.yaml | 21 ++++++++++++--------- README.md | 8 ++++---- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/API/openapi.yaml b/API/openapi.yaml index 5186d81..1c8de72 100644 --- a/API/openapi.yaml +++ b/API/openapi.yaml @@ -12,6 +12,8 @@ openapi: "3.0.0" # - Rules for RESTful error code RFC2616: https://datatracker.ietf.org/doc/html/rfc2616#section-10 # - Guide: https://restfulapi.net/http-status-codes/ # +# Last Version: 04.03.2022 +# info: version: 0.0.4 title: World Storage API @@ -25,6 +27,7 @@ paths: /ping: get: summary: Test the server availability + operationId: getPing responses: '200': description: OK, world storage alive. @@ -56,9 +59,9 @@ paths: application/json: schema: $ref: '#/components/schemas/Trackable' - application/xml: - schema: - $ref: '#/components/schemas/Trackable' + #application/xml: + # schema: + # $ref: '#/components/schemas/Trackable' responses: '200': description: OK, returns the UUID of the Trackable defined by the world storage. @@ -155,9 +158,9 @@ paths: application/json: schema: $ref: '#/components/schemas/WorldAnchor' - application/xml: - schema: - $ref: '#/components/schemas/WorldAnchor' + #application/xml: + # schema: + # $ref: '#/components/schemas/WorldAnchor' responses: '200': description: OK, returns the UUID of the World Anchor defined by the world storage. @@ -254,9 +257,9 @@ paths: application/json: schema: $ref: '#/components/schemas/WorldLink' - application/xml: - schema: - $ref: '#/components/schemas/WorldLink' + #application/xml: + # schema: + # $ref: '#/components/schemas/WorldLink' responses: '200': description: OK, returns the UUID of the link defined by the world storage. diff --git a/README.md b/README.md index a45f4c5..1012339 100644 --- a/README.md +++ b/README.md @@ -115,19 +115,19 @@ Install the tool with "npm", see: https://openapi-generator.tech/docs/installati ### Validating the api -> npx @openapitools/openapi-generator-cli validate -i .\openapi.yaml +> npx @openapitools/openapi-generator-cli validate -i API/openapi.yaml ### Example C++ Server (Pistache) -> npx @openapitools/openapi-generator-cli generate -i openapi.yaml -g cpp-pistache-server -o ./codeGeneration/sever/cpp/pistache +> npx @openapitools/openapi-generator-cli generate -i API/openapi.yaml -g cpp-pistache-server -o ./CodeGeneration/sever/cpp/pistache ### Example ASP.NET Server (C#) -> npx @openapi-generator-cli generate -i openapi.yaml -g aspnetcore -o ./codeGeneration/server/aspnetcore +> npx @openapitools/openapi-generator-cli generate -i API/openapi.yaml -g aspnetcore -o ./CodeGeneration/server/aspnetcore ### Example C# Client -> npx @openapitools/openapi-generator-cli generate -i openapi.yaml -g csharp-netcore -o ./codeGeneration/client/c#/netcore +> npx @openapitools/openapi-generator-cli generate -i API/openapi.yaml -g csharp -o ./CodeGeneration/client/csharp # Branching Policy Distributed version control systems like Git offers developers great flexibility to share and manage code. But a branching policy is crucial to collaborate more easily while keeping track of releases with bug fixes. -- GitLab From 8f5aa002955d48e80aabf1cafa2e2a8efb78dc37 Mon Sep 17 00:00:00 2001 From: Nathan Chambron Date: Fri, 8 Apr 2022 12:29:24 +0000 Subject: [PATCH 14/29] change trackable required attribute from keyvalueTagList to keyvalueTags --- API/openapi.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/API/openapi.yaml b/API/openapi.yaml index 1c8de72..11d0c9d 100644 --- a/API/openapi.yaml +++ b/API/openapi.yaml @@ -396,7 +396,7 @@ components: - localCRS - unit - trackableSize - - keyvalueTagList + - keyvalueTags properties: UUID: description: A Universally Unique IDentifier identifying the trackable (RFC 4122). -- GitLab From 5da5faa719bcb310bc57ae97168e582218d1355c Mon Sep 17 00:00:00 2001 From: Nathan Chambron Date: Fri, 8 Apr 2022 12:35:53 +0000 Subject: [PATCH 15/29] Update openapi.yaml --- API/openapi.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/API/openapi.yaml b/API/openapi.yaml index 11d0c9d..eef5f94 100644 --- a/API/openapi.yaml +++ b/API/openapi.yaml @@ -436,7 +436,7 @@ components: - localCRS - unit - worldAnchorSize - - keyvalueTagList + - keyvalueTags properties: UUID: description: A Universally Unique IDentifier identifying the world anchor (RFC 4122). -- GitLab From 2ae1ba5583a0e3ae90f7d59507b8dbbc6da11f25 Mon Sep 17 00:00:00 2001 From: Sylvain Renault Date: Wed, 27 Apr 2022 10:42:14 +0200 Subject: [PATCH 16/29] Trackables and anchors now have a name param (naming the elements are crucial to understand the graph and useful for the GUI). New ObjectType (NotIdentified) for to/from of a WorldLink when element is deleted from the graph. New encoding types: vuforia, aruco. --- API/openapi.yaml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/API/openapi.yaml b/API/openapi.yaml index eef5f94..438e177 100644 --- a/API/openapi.yaml +++ b/API/openapi.yaml @@ -389,6 +389,7 @@ components: Trackable: type: object required: + - name - creatorUUID - trackableType - trackableEncodingInformation @@ -403,6 +404,10 @@ components: type: string format: uuid example: fa8bbe40-8052-11ec-a8a3-0242ac120002 + name: + description: A human readable name for the trackable. + type: string + example: newTrackableXYZ creatorUUID: description: A Universally Unique IDentifier identifying the creator of the trackable (a person, a team or a company). type: string @@ -432,6 +437,7 @@ components: WorldAnchor: type: object required: + - name - creatorUUID - localCRS - unit @@ -443,6 +449,10 @@ components: type: string format: uuid example: ce8ccd80-56ee-2a5c-a8a3-0242ac150d002 + name: + description: A human readable name for the world anchor. + type: string + example: newWorldAnchorXYZ creatorUUID: description: A Universally Unique IDentifier identifying the creator of the world anchor. type: string @@ -536,7 +546,7 @@ components: dataFormat: description: Identifier of the target framework type: string - enum: [HOLOLENS, ARKIT, ARCORE] + enum: [HOLOLENS, ARKIT, ARCORE, VUFORIA, ARUCO] example : "HOLOLENS" version: description: The version of the format @@ -559,7 +569,7 @@ components: ObjectType: description: Type of an world representaion object. type: string - enum: [Trackable, WorldAnchor, WorldLink] + enum: [Trackable, WorldAnchor, WorldLink, NotIdentified] example: Trackable UnitSystem: -- GitLab From 8b7f93276f0f211ca38917ee3ccca490bb40a990 Mon Sep 17 00:00:00 2001 From: Sylvain Renault Date: Fri, 29 Apr 2022 10:58:35 +0200 Subject: [PATCH 17/29] Minor changes in the yaml file (format) --- API/openapi.yaml | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/API/openapi.yaml b/API/openapi.yaml index 438e177..75e7b74 100644 --- a/API/openapi.yaml +++ b/API/openapi.yaml @@ -15,7 +15,7 @@ openapi: "3.0.0" # Last Version: 04.03.2022 # info: - version: 0.0.4 + version: 0.0.5 title: World Storage API description: API ensuring interoperability between an authoring tool and a World Storage service license: @@ -376,7 +376,7 @@ components: name: UUID in: path required: true - description: A Universally Unique IDentifier identifying the object + description: A Universally Unique IDentifier identifying the object (RFC 4122). schema: type: string format: uuid @@ -407,7 +407,7 @@ components: name: description: A human readable name for the trackable. type: string - example: newTrackableXYZ + example: myTrackableXYZ creatorUUID: description: A Universally Unique IDentifier identifying the creator of the trackable (a person, a team or a company). type: string @@ -426,13 +426,13 @@ components: format: byte example: "10110101" localCRS: - $ref: '#/components/schemas/Transform3D' + $ref: '#/components/schemas/Transform3D' unit: - $ref: '#/components/schemas/UnitSystem' + $ref: '#/components/schemas/UnitSystem' trackableSize: - $ref: '#/components/schemas/Size' + $ref: '#/components/schemas/Size' keyvalueTags: - $ref: '#/components/schemas/KeyvalueTagList' + $ref: '#/components/schemas/KeyvalueTagList' WorldAnchor: type: object @@ -452,20 +452,20 @@ components: name: description: A human readable name for the world anchor. type: string - example: newWorldAnchorXYZ + example: myWorldAnchorXYZ creatorUUID: description: A Universally Unique IDentifier identifying the creator of the world anchor. type: string format: uuid example: c75f6324-77a0-11ec-90d6-0242ac120003 localCRS: - $ref: '#/components/schemas/Transform3D' + $ref: '#/components/schemas/Transform3D' unit: - $ref: '#/components/schemas/UnitSystem' + $ref: '#/components/schemas/UnitSystem' worldAnchorSize: - $ref: '#/components/schemas/Size' + $ref: '#/components/schemas/Size' keyvalueTags: - $ref: '#/components/schemas/KeyvalueTagList' + $ref: '#/components/schemas/KeyvalueTagList' WorldLink: type: object @@ -499,15 +499,15 @@ components: format: uuid example: ce8ccd80-56ee-2a5c-a8a3-0242ac150d002 transform: - $ref: '#/components/schemas/Transform3D' + $ref: '#/components/schemas/Transform3D' unit: - $ref: '#/components/schemas/UnitSystem' + $ref: '#/components/schemas/UnitSystem' linkSize: - $ref: '#/components/schemas/Size' + $ref: '#/components/schemas/Size' keyvalueTags: - description: List of additional parameters to be stored - $ref: '#/components/schemas/KeyvalueTagList' - example: { "LinkType" : ["Hierarchy"]} + description: List of additional parameters to be stored + $ref: '#/components/schemas/KeyvalueTagList' + example: { "LinkType" : ["Hierarchy"]} AttachedObjects: type: object @@ -546,7 +546,7 @@ components: dataFormat: description: Identifier of the target framework type: string - enum: [HOLOLENS, ARKIT, ARCORE, VUFORIA, ARUCO] + enum: [HOLOLENS, ARKIT, ARCORE, VUFORIA, ARUCO, OTHER] example : "HOLOLENS" version: description: The version of the format @@ -559,8 +559,8 @@ components: minItems: 16 maxItems: 16 items: - type: number - format: float + type: number + format: float example: [-2, 1,-3, 4, 4, 4, 4, 2, 1, 0,-2, 1, -- GitLab From c8802a3a9846a3b82f9e88cf002d01c324c91b13 Mon Sep 17 00:00:00 2001 From: Sylvain Renault Date: Fri, 29 Apr 2022 11:27:21 +0200 Subject: [PATCH 18/29] New admin operation "getVersion" to receive the current version number of the API. --- API/openapi.yaml | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/API/openapi.yaml b/API/openapi.yaml index 75e7b74..b5e8da9 100644 --- a/API/openapi.yaml +++ b/API/openapi.yaml @@ -33,11 +33,22 @@ paths: description: OK, world storage alive. /admin: get: - summary: Get the version of the API. + summary: Get the state of the server. + operationId: getAdmin + responses: + '200': + description: OK, world storage server ready. + content: + text/plain: + schema: + type: string + /version: + get: + summary: Get the version of the ARF API. operationId: getVersion responses: '200': - description: OK, world storage ready. + description: Current version. content: text/plain: schema: @@ -505,7 +516,7 @@ components: linkSize: $ref: '#/components/schemas/Size' keyvalueTags: - description: List of additional parameters to be stored + description: List of additional parameters to be stored. $ref: '#/components/schemas/KeyvalueTagList' example: { "LinkType" : ["Hierarchy"]} @@ -589,7 +600,7 @@ components: example: [1,5,0] KeyvalueTagList: - description: List of additional parameters to be stored with the trackable. + description: List of additional parameters to be stored with the object. type: object additionalProperties: type: array -- GitLab From f5d83e4018c51b6221adc06e4bcec48a980f7eae Mon Sep 17 00:00:00 2001 From: Sylvain Renault Date: Tue, 17 May 2022 16:15:39 +0200 Subject: [PATCH 19/29] New draft version - deleted AttachedObjects (action + schema) - new version number - some new descriptions - new default matrix - new default UUID (all are now differents) --- API/openapi.yaml | 125 ++++++++++++++++------------------------------- 1 file changed, 41 insertions(+), 84 deletions(-) diff --git a/API/openapi.yaml b/API/openapi.yaml index b5e8da9..7414cee 100644 --- a/API/openapi.yaml +++ b/API/openapi.yaml @@ -9,13 +9,14 @@ openapi: "3.0.0" # - Explaination UUID: https://en.wikipedia.org/wiki/Universally_unique_identifier / https://fr.wikipedia.org/wiki/Universally_unique_identifier # - UUID formats: 8-4-4-4-12 format string, lower case (but case insensitive on input) # - UUID RFC4122: https://datatracker.ietf.org/doc/html/rfc4122#section-3 +# - online UUID generator: https://www.uuidgenerator.net/ # - Rules for RESTful error code RFC2616: https://datatracker.ietf.org/doc/html/rfc2616#section-10 # - Guide: https://restfulapi.net/http-status-codes/ # -# Last Version: 04.03.2022 +# Last Version: 17.05.2022 # info: - version: 0.0.5 + version: 0.0.6 title: World Storage API description: API ensuring interoperability between an authoring tool and a World Storage service license: @@ -351,32 +352,6 @@ paths: '404': $ref: '#/components/responses/404_NotFoundUUID' - /worldLinks/attached/{worldLinkUUID}: - get: - summary: Retrieve end objects connected to this world link by its UUID. - operationId: getAttachedObjectsFromUUID - tags: - - world links - parameters: - - name: worldLinkUUID - in: path - description: UUID of the link from which you will retrieve the end objects. - required: true - schema: - type: string - format: uuid - responses: - '200': - description: Successful operation. - content: - application/json: - schema: - $ref: '#/components/schemas/AttachedObjects' - '400': - $ref: '#/components/responses/400_InvalidUUID' - '404': - $ref: '#/components/responses/404_NotFoundUUID' - # COMPONENTS ############################################### components: #------------------------------- @@ -387,7 +362,7 @@ components: name: UUID in: path required: true - description: A Universally Unique IDentifier identifying the object (RFC 4122). + description: An Universally Unique IDentifier identifying the object (RFC 4122). schema: type: string format: uuid @@ -398,6 +373,7 @@ components: #------------------------------- schemas: Trackable: + description: An element representing a trackable object in the real world. type: object required: - name @@ -411,7 +387,7 @@ components: - keyvalueTags properties: UUID: - description: A Universally Unique IDentifier identifying the trackable (RFC 4122). + description: An Universally Unique IDentifier identifying the trackable (RFC 4122). type: string format: uuid example: fa8bbe40-8052-11ec-a8a3-0242ac120002 @@ -420,14 +396,14 @@ components: type: string example: myTrackableXYZ creatorUUID: - description: A Universally Unique IDentifier identifying the creator of the trackable (a person, a team or a company). + description: An Universally Unique IDentifier identifying the creator of the trackable (a person, a team or a company). type: string format: uuid - example: c75f6324-77a0-11ec-90d6-0242ac120003 + example: bd6ce7ce-7fe8-487d-a179-fddfe914f293 trackableType: description: Extensible list of trackable types possibly handled by complient World Storage implementation. type: string - enum: [FIDUCIAL_MARKER, IMAGE_MARKER, MAP, OTHER] + enum: [FIDUCIAL_MARKER, IMAGE_MARKER, MAP, GEOPOSITION, OTHER] example: FIDUCIAL_MARKER trackableEncodingInformation: $ref: '#/components/schemas/EncodingInformationStructure' @@ -443,9 +419,12 @@ components: trackableSize: $ref: '#/components/schemas/Size' keyvalueTags: + description: List of additional parameters to be stored. $ref: '#/components/schemas/KeyvalueTagList' + example: { "TrackableType" : ["Standard"]} WorldAnchor: + description: An element describing a pose in the world graph. type: object required: - name @@ -456,19 +435,19 @@ components: - keyvalueTags properties: UUID: - description: A Universally Unique IDentifier identifying the world anchor (RFC 4122). + description: An Universally Unique IDentifier identifying the world anchor (RFC 4122). type: string format: uuid - example: ce8ccd80-56ee-2a5c-a8a3-0242ac150d002 + example: 49d18ab3-1bf8-481d-919b-cd062a2fd428 name: description: A human readable name for the world anchor. type: string example: myWorldAnchorXYZ creatorUUID: - description: A Universally Unique IDentifier identifying the creator of the world anchor. + description: An Universally Unique IDentifier identifying the creator of the world anchor. type: string format: uuid - example: c75f6324-77a0-11ec-90d6-0242ac120003 + example: 6ddeb59e-7740-42f7-b329-1374b92e7fc2 localCRS: $ref: '#/components/schemas/Transform3D' unit: @@ -476,9 +455,12 @@ components: worldAnchorSize: $ref: '#/components/schemas/Size' keyvalueTags: + description: List of additional parameters to be stored. $ref: '#/components/schemas/KeyvalueTagList' + example: { "AnchorType" : ["Static"]} WorldLink: + description: An object holding the info of a transform between two elements. type: object required: - creatorUUID @@ -490,25 +472,29 @@ components: - keyvalueTags properties: UUID: - description: A Universally Unique IDentifier identifying the link (RFC 4122). + description: An Universally Unique IDentifier identifying the link (RFC 4122). type: string format: uuid - example: ce8ccd80-56ee-2a5c-a8a3-0242ac150d002 + example: c6998f4f-1b8d-460b-9de8-4793b92fae2a creatorUUID: - description: A Universally Unique IDentifier identifying the creator of the link. + description: An Universally Unique IDentifier identifying the creator of the link. type: string format: uuid - example: c75f6324-77a0-11ec-90d6-0242ac120003 + example: 7506001c-9c00-4f84-ae2e-e4dfcb77d36a UUIDFrom: - description: A Universally Unique IDentifier identifying a world anchor or trackable. + description: An Universally Unique IDentifier identifying a world anchor or trackable. type: string format: uuid - example: ce8ccd80-56ee-2a5c-a8a3-0242ac150d002 + example: 60e11d81-1230-4588-be4c-93520a275012 UUIDTo: - description: A Universally Unique IDentifier identifying a world anchor or trackable. + description: An Universally Unique IDentifier identifying a world anchor or trackable. type: string format: uuid - example: ce8ccd80-56ee-2a5c-a8a3-0242ac150d002 + example: 85eed503-875c-4d3d-9569-06c4859bd4cd + typeFrom: + $ref: '#/components/schemas/ObjectType' + typeTo: + $ref: '#/components/schemas/ObjectType' transform: $ref: '#/components/schemas/Transform3D' unit: @@ -520,42 +506,13 @@ components: $ref: '#/components/schemas/KeyvalueTagList' example: { "LinkType" : ["Hierarchy"]} - AttachedObjects: - type: object - required: - - UUID - - UUIDFrom - - UUIDTo - - TypeFrom - - TypeTo - properties: - UUID: - description: A Universally Unique IDentifier identifying the link. - type: string - format: uuid - example: ce8ccd80-56ee-2a5c-a8a3-0242ac150d002 - UUIDFrom: - description: A Universally Unique IDentifier identifying a world anchor or trackable. - type: string - format: uuid - example: ce8ccd80-56ee-2a5c-a8a3-0242ac150d002 - UUIDTo: - description: A Universally Unique IDentifier identifying a world anchor or trackable. - type: string - format: uuid - example: ce8ccd80-56ee-2a5c-a8a3-0242ac150d002 - TypeFrom: - $ref: '#/components/schemas/ObjectType' - TypeTo: - $ref: '#/components/schemas/ObjectType' - EncodingInformationStructure: required: - dataFormat - version properties: dataFormat: - description: Identifier of the target framework + description: Identifier of the target framework. type: string enum: [HOLOLENS, ARKIT, ARCORE, VUFORIA, ARUCO, OTHER] example : "HOLOLENS" @@ -565,22 +522,22 @@ components: example : "1.01" Transform3D: - description: Coordinate reference system of the world anchor, a 4*4 matrix (rowmajor) represented by a float vector + description: Coordinate reference system of the world anchor, a 4*4 matrix (rowmajor) represented by a float vector. type: array minItems: 16 maxItems: 16 items: type: number format: float - example: [-2, 1,-3, 4, - 4, 4, 4, 2, - 1, 0,-2, 1, - -1,-2, 0, 0] + example: [ 1, 0, 0, 3, + 0, 1, 0, 3, + 0, 0, 1, 3, + 0, 0, 0, 1] ObjectType: - description: Type of an world representaion object. + description: Type of a world representaion object. type: string - enum: [Trackable, WorldAnchor, WorldLink, NotIdentified] + enum: [Trackable, WorldAnchor, NotIdentified] example: Trackable UnitSystem: @@ -597,7 +554,7 @@ components: format: double minItems: 3 maxItems: 3 - example: [1,5,0] + example: [1.0,1.0,1.5] KeyvalueTagList: description: List of additional parameters to be stored with the object. @@ -607,7 +564,7 @@ components: items: type: string minItems: 1 - example: { "Place" : ["Museum 1"], "room" : ["B4"]} + example: { "Place" : ["Building 123"], "Room" : ["007"]} Error: required: -- GitLab From 8b13db35ec8349a8bf513f9ad1d35d6a24699a00 Mon Sep 17 00:00:00 2001 From: Sylvain Renault Date: Tue, 17 May 2022 16:30:19 +0200 Subject: [PATCH 20/29] Some changes in the md file. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1012339..6c0c54f 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ # Objectives -Project dedicated to the development of an API standardizing the exchanges with a World Storage Representation service. +This repository is dedicated to the development of the augmented reality framework (ARF) API (ETSI-ISG) for standardizing the exchanges with a World Storage. service. The API contains all the accees actions (REST) data (elements) needed to implement a World Representation with a World Graph. # Associated workspaces -- GitLab From 32912d4d7613c10a4577144361291f65fdd15ebb Mon Sep 17 00:00:00 2001 From: Jerome Royan Date: Tue, 24 May 2022 12:35:15 +0000 Subject: [PATCH 21/29] Yes, you are right, the position is to less. GEOPOSE is better. --- API/openapi.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/API/openapi.yaml b/API/openapi.yaml index 7414cee..d8ea76e 100644 --- a/API/openapi.yaml +++ b/API/openapi.yaml @@ -403,7 +403,7 @@ components: trackableType: description: Extensible list of trackable types possibly handled by complient World Storage implementation. type: string - enum: [FIDUCIAL_MARKER, IMAGE_MARKER, MAP, GEOPOSITION, OTHER] + enum: [FIDUCIAL_MARKER, IMAGE_MARKER, MAP, GEOPOSE, OTHER] example: FIDUCIAL_MARKER trackableEncodingInformation: $ref: '#/components/schemas/EncodingInformationStructure' -- GitLab From d3466c43668f8b4ca3b99121caab7a2cac47b0ef Mon Sep 17 00:00:00 2001 From: Nathan Chambron Date: Tue, 31 May 2022 10:44:10 +0200 Subject: [PATCH 22/29] format: refactor spec to add doc --- API/openapi.yaml | 179 ++++++++++++++++++++++------------------------- 1 file changed, 83 insertions(+), 96 deletions(-) diff --git a/API/openapi.yaml b/API/openapi.yaml index d8ea76e..4d6b7de 100644 --- a/API/openapi.yaml +++ b/API/openapi.yaml @@ -1,9 +1,7 @@ -openapi: "3.0.0" -# +# Copyright 2022 ETSI. Licensed under the BSD-3-Clause license # API for the Augmented Reality Framework (ARF) # Working group: ETSI ISG ARF # STF group: STF620 (validation) -# (C) ETSI - 2022 # # References: # - Explaination UUID: https://en.wikipedia.org/wiki/Universally_unique_identifier / https://fr.wikipedia.org/wiki/Universally_unique_identifier @@ -14,16 +12,29 @@ openapi: "3.0.0" # - Guide: https://restfulapi.net/http-status-codes/ # # Last Version: 17.05.2022 -# + +openapi: "3.0.0" + info: version: 0.0.6 title: World Storage API description: API ensuring interoperability between an authoring tool and a World Storage service license: - name: BSD-3-clause + name: Copyright 2022 ETSI. Licensed under the BSD-3-Clause license url: https://opensource.org/licenses/BSD-3-Clause servers: - url: http://localhost:8080 + +tags: + - name: default + description: Default operations to test the current server's state + - name: Trackables + description: Trackables are models of parts of the real world.
Trackables are elements of the real world of which features are available and/or could be extracted.
Trackables provide a Coordinate Reference System in which a pose can be expressed. + - name: World Anchors + description: A World Anchor represents a fixed position in relation to one or more elements of the real world.
It has a Coordinate Reference System in which AR Assets stay spatially-registered. + - name: World Links + description: A World Link represents and defines the relative 3D position and orientation between elements (Trackables and/or World Anchors). + paths: /ping: get: @@ -38,45 +49,35 @@ paths: operationId: getAdmin responses: '200': - description: OK, world storage server ready. - content: - text/plain: - schema: - type: string + description: OK, world storage server ready. /version: get: summary: Get the version of the ARF API. operationId: getVersion responses: '200': - description: Current version. - content: - text/plain: - schema: - type: string + description: Current version. ############## # TRACKABLES # ############## /trackables: post: - summary: Create a trackable. + summary: Create a Trackable. operationId: addTrackable + description: Create a new Trackable from a json object containing all the required informations and add it to the world storage.
As a result you will get the ID of the newly created Trackable. tags: - - trackables + - Trackables requestBody: - description: The trackable to be added to the world storage. + description: The Trackable to be added to the world storage. required: true content: application/json: schema: $ref: '#/components/schemas/Trackable' - #application/xml: - # schema: - # $ref: '#/components/schemas/Trackable' responses: '200': - description: OK, returns the UUID of the Trackable defined by the world storage. + description: OK, return the UUID of the Trackable defined by the world storage. content: text/plain: schema: @@ -90,13 +91,14 @@ paths: 'default': $ref: '#/components/responses/4xx_UnexpectedError' get: - summary: Returns the list of all trackables defined by the world storage. + summary: Return all the Trackables. operationId: getTrackables + description: Get all the Trackables currently being stored in the world storage. tags: - - trackables + - Trackables responses: '200': - description: OK, returns all the Trackables defined by the world storage. + description: OK, return all the Trackables defined by the world storage. content: application/json: schema: @@ -112,12 +114,13 @@ paths: get: summary: Find a trackable by its UUID. operationId: getTrackableById + description: Get a single Trackable stored in the world storage from its ID. tags: - - trackables + - Trackables parameters: - name: trackableUUID in: path - description: UUID of the trackable to retrieve. + description: UUID of the Trackable to retrieve. required: true schema: type: string @@ -134,10 +137,11 @@ paths: '404': $ref: '#/components/responses/404_NotFoundUUID' delete: - summary: Deletes a trackable. + summary: Delete a Trackable. operationId: deleteTrackable + description: Delete a single Trackable stored in the world storage from its ID. tags: - - trackables + - Trackables parameters: - name: trackableUUID in: path @@ -159,23 +163,21 @@ paths: ################# /worldAnchors: post: - summary: Create a world anchor. + summary: Create a World Anchor. operationId: addWorldAnchor + description: Create a new World Anchor from a json object containing all the required informations and add it to the world storage.
As a result you will get the ID of the newly created World Anchor. tags: - - world anchors + - World Anchors requestBody: - description: The world anchor to be added to the world storage. + description: The World Anchor to be added to the world storage. required: true content: application/json: schema: - $ref: '#/components/schemas/WorldAnchor' - #application/xml: - # schema: - # $ref: '#/components/schemas/WorldAnchor' + $ref: '#/components/schemas/WorldAnchor' responses: '200': - description: OK, returns the UUID of the World Anchor defined by the world storage. + description: OK, return the UUID of the World Anchor defined by the world storage. content: text/plain: schema: @@ -189,13 +191,14 @@ paths: 'default': $ref: '#/components/responses/4xx_UnexpectedError' get: - summary: Returns the list of all world anchors defined by the world storage. + summary: Return all the World Anchors. operationId: getWorldAnchors + description: Get all the World Anchors currently being stored in the world storage. tags: - - world anchors + - World Anchors responses: '200': - description: OK, returns all the world anchors defined by the world storage. + description: OK, return all the World Anchors defined by the world storage. content: application/json: schema: @@ -209,14 +212,15 @@ paths: /worldAnchors/{worldAnchorUUID}: get: - summary: Find a world anchor by its UUID. + summary: Find a World Anchor by its UUID. operationId: getWorldAnchorById + description: Get a single World Anchor stored in the world storage from its ID. tags: - - world anchors + - World Anchors parameters: - name: worldAnchorUUID in: path - description: UUID of the world anchor to retrieve. + description: UUID of the World Anchor to retrieve. required: true schema: type: string @@ -233,14 +237,15 @@ paths: '404': $ref: '#/components/responses/404_NotFoundUUID' delete: - summary: Deletes a world anchor. + summary: Delete a World Anchor. operationId: deleteWorldAnchor + description: Delete a single World Anchor stored in the world storage from its ID. tags: - - world anchors + - World Anchors parameters: - name: worldAnchorUUID in: path - description: World anchor UUID to delete. + description: World Anchor UUID to delete. required: true schema: type: string @@ -258,10 +263,11 @@ paths: ############### /worldLinks: post: - summary: Create a link between world anchors and trackables. + summary: Create a World Link between elements (world anchors and/or trackables). operationId: addWorldLink + description: Create a new World Link from a json object containing all the required informations and add it to the world storage.
As a result you will get the ID of the newly created World Link. tags: - - world links + - World Links requestBody: description: The link to be added to the world storage. required: true @@ -269,12 +275,9 @@ paths: application/json: schema: $ref: '#/components/schemas/WorldLink' - #application/xml: - # schema: - # $ref: '#/components/schemas/WorldLink' responses: '200': - description: OK, returns the UUID of the link defined by the world storage. + description: OK, return the UUID of the World Link defined by the world storage. content: text/plain: schema: @@ -288,13 +291,14 @@ paths: 'default': $ref: '#/components/responses/4xx_UnexpectedError' get: - summary: Returns the list of all links defined by the world storage. + summary: Return all World Links. + description: Get all the World Links currently being stored in the world storage. operationId: getWorldLinks tags: - - world links + - World Links responses: '200': - description: OK returns all the worldLinks defined by the world storage. + description: OK return all the World Links defined by the world storage. content: application/json: schema: @@ -308,14 +312,15 @@ paths: /worldLinks/{worldLinkUUID}: get: - summary: Find a link by its UUID. + summary: Find a World Link by its UUID. operationId: getWorldLinkById + description: Get a single World Link stored in the world storage from its ID. tags: - - world links + - World Links parameters: - name: worldLinkUUID in: path - description: UUID of the link to retrieve. + description: UUID of the World Link to retrieve. required: true schema: type: string @@ -332,14 +337,15 @@ paths: '404': $ref: '#/components/responses/404_NotFoundUUID' delete: - summary: Deletes a worldLink. + summary: Delete a World Link. operationId: deleteWorldLink + description: Delete a single World Link stored in the world storage from its ID. tags: - - world links + - World Links parameters: - name: worldLinkUUID in: path - description: link id to delete + description: World Link id to delete. required: true schema: type: string @@ -354,26 +360,13 @@ paths: # COMPONENTS ############################################### components: - #------------------------------- - # Reusable operation parameters - #------------------------------- - parameters: - UUIDParams: - name: UUID - in: path - required: true - description: An Universally Unique IDentifier identifying the object (RFC 4122). - schema: - type: string - format: uuid - default: "00000000-0000-0000-0000-000000000000" #------------------------------- # Reusable schemas (data models) #------------------------------- schemas: Trackable: - description: An element representing a trackable object in the real world. + description: An element representing a Trackable object in the real world. type: object required: - name @@ -387,28 +380,28 @@ components: - keyvalueTags properties: UUID: - description: An Universally Unique IDentifier identifying the trackable (RFC 4122). + description: An Universally Unique IDentifier identifying the Trackable (RFC 4122). type: string format: uuid example: fa8bbe40-8052-11ec-a8a3-0242ac120002 name: - description: A human readable name for the trackable. + description: A human readable name for the Trackable. type: string example: myTrackableXYZ creatorUUID: - description: An Universally Unique IDentifier identifying the creator of the trackable (a person, a team or a company). + description: An Universally Unique IDentifier identifying the creator of the Trackable (a person, a team or a company). type: string format: uuid example: bd6ce7ce-7fe8-487d-a179-fddfe914f293 trackableType: - description: Extensible list of trackable types possibly handled by complient World Storage implementation. + description: Extensible list of Trackable types, possibly handled by complient world storage implementation. type: string enum: [FIDUCIAL_MARKER, IMAGE_MARKER, MAP, GEOPOSE, OTHER] example: FIDUCIAL_MARKER trackableEncodingInformation: $ref: '#/components/schemas/EncodingInformationStructure' trackablePayload: - description: The data provided to create the trackable in a specific format handled by the World Storage service. + description: The data provided to create the Trackable in a specific format handled by the world storage service. type: string format: byte example: "10110101" @@ -419,9 +412,7 @@ components: trackableSize: $ref: '#/components/schemas/Size' keyvalueTags: - description: List of additional parameters to be stored. $ref: '#/components/schemas/KeyvalueTagList' - example: { "TrackableType" : ["Standard"]} WorldAnchor: description: An element describing a pose in the world graph. @@ -435,16 +426,16 @@ components: - keyvalueTags properties: UUID: - description: An Universally Unique IDentifier identifying the world anchor (RFC 4122). + description: An Universally Unique IDentifier identifying the World Anchor (RFC 4122). type: string format: uuid example: 49d18ab3-1bf8-481d-919b-cd062a2fd428 name: - description: A human readable name for the world anchor. + description: A human readable name for the World Anchor. type: string example: myWorldAnchorXYZ creatorUUID: - description: An Universally Unique IDentifier identifying the creator of the world anchor. + description: An Universally Unique IDentifier identifying the creator of the World Anchor. type: string format: uuid example: 6ddeb59e-7740-42f7-b329-1374b92e7fc2 @@ -455,9 +446,7 @@ components: worldAnchorSize: $ref: '#/components/schemas/Size' keyvalueTags: - description: List of additional parameters to be stored. $ref: '#/components/schemas/KeyvalueTagList' - example: { "AnchorType" : ["Static"]} WorldLink: description: An object holding the info of a transform between two elements. @@ -472,22 +461,22 @@ components: - keyvalueTags properties: UUID: - description: An Universally Unique IDentifier identifying the link (RFC 4122). + description: An Universally Unique IDentifier identifying the World Link (RFC 4122). type: string format: uuid example: c6998f4f-1b8d-460b-9de8-4793b92fae2a creatorUUID: - description: An Universally Unique IDentifier identifying the creator of the link. + description: An Universally Unique IDentifier identifying the creator of the World Link. type: string format: uuid example: 7506001c-9c00-4f84-ae2e-e4dfcb77d36a UUIDFrom: - description: An Universally Unique IDentifier identifying a world anchor or trackable. + description: An Universally Unique IDentifier identifying a World Anchor or Trackable. type: string format: uuid example: 60e11d81-1230-4588-be4c-93520a275012 UUIDTo: - description: An Universally Unique IDentifier identifying a world anchor or trackable. + description: An Universally Unique IDentifier identifying a World Anchor or Trackable. type: string format: uuid example: 85eed503-875c-4d3d-9569-06c4859bd4cd @@ -499,14 +488,11 @@ components: $ref: '#/components/schemas/Transform3D' unit: $ref: '#/components/schemas/UnitSystem' - linkSize: - $ref: '#/components/schemas/Size' keyvalueTags: - description: List of additional parameters to be stored. $ref: '#/components/schemas/KeyvalueTagList' - example: { "LinkType" : ["Hierarchy"]} EncodingInformationStructure: + description: An object holding the info of a Trackable`'`s encoding informations `:` the data format and the version. required: - dataFormat - version @@ -547,7 +533,7 @@ components: example: M Size: - description: Size {width, length, depth}. + description: Size object in format {width, length, depth}. type: array items: type: number @@ -576,6 +562,7 @@ components: format: int32 message: type: string + #------------------------------- # Reusable responses #------------------------------- -- GitLab From b57c44eb07bdce4fa153eeec759e7141d63a35c7 Mon Sep 17 00:00:00 2001 From: Nathan Chambron Date: Tue, 31 May 2022 11:03:01 +0200 Subject: [PATCH 23/29] feat: add put endpoints for Trackable, World Anchors and Wolrd Links --- API/openapi.yaml | 80 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 69 insertions(+), 11 deletions(-) diff --git a/API/openapi.yaml b/API/openapi.yaml index 4d6b7de..4f710f9 100644 --- a/API/openapi.yaml +++ b/API/openapi.yaml @@ -77,11 +77,7 @@ paths: $ref: '#/components/schemas/Trackable' responses: '200': - description: OK, return the UUID of the Trackable defined by the world storage. - content: - text/plain: - schema: - type: string + description: OK, return the UUID of the Trackable defined by the world storage. '201': description: Null response. '400': @@ -90,6 +86,28 @@ paths: $ref: '#/components/responses/409_NotEmptyUUID' 'default': $ref: '#/components/responses/4xx_UnexpectedError' + put: + summary: Modify a Trackable. + operationId: modifyTrackable + description: Modify an existing Trackable given a json object containing all the required informations.
**Please note that ID of the object is required in the JSON** + tags: + - Trackables + requestBody: + description: The Trackable to be modified in the world storage. + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Trackable' + responses: + '200': + description: OK, return the UUID of the modified Trackable. + '400': + $ref: '#/components/responses/400_BadRequest' + '404': + $ref: '#/components/responses/404_NotFoundUUID' + 'default': + $ref: '#/components/responses/4xx_UnexpectedError' get: summary: Return all the Trackables. operationId: getTrackables @@ -112,7 +130,7 @@ paths: /trackables/{trackableUUID}: get: - summary: Find a trackable by its UUID. + summary: Find a Trackable by its UUID. operationId: getTrackableById description: Get a single Trackable stored in the world storage from its ID. tags: @@ -177,11 +195,7 @@ paths: $ref: '#/components/schemas/WorldAnchor' responses: '200': - description: OK, return the UUID of the World Anchor defined by the world storage. - content: - text/plain: - schema: - type: string + description: OK, return the UUID of the World Anchor defined by the world storage. '201': description: Null response. '400': @@ -190,6 +204,28 @@ paths: $ref: '#/components/responses/409_NotEmptyUUID' 'default': $ref: '#/components/responses/4xx_UnexpectedError' + put: + summary: Modify a World Anchor. + operationId: modifyWorldAnchor + description: Modify an existing World Anchor given a json object containing all the required informations.
**Please note that ID of the object is required in the JSON** + tags: + - World Anchors + requestBody: + description: The World Anchor to be modified in the world storage. + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/WorldAnchor' + responses: + '200': + description: OK, return the UUID of the modified World Anchor. + '400': + $ref: '#/components/responses/400_BadRequest' + '404': + $ref: '#/components/responses/404_NotFoundUUID' + 'default': + $ref: '#/components/responses/4xx_UnexpectedError' get: summary: Return all the World Anchors. operationId: getWorldAnchors @@ -290,6 +326,28 @@ paths: $ref: '#/components/responses/409_NotEmptyUUID' 'default': $ref: '#/components/responses/4xx_UnexpectedError' + put: + summary: Modify a World Link. + operationId: modifyWorldLink + description: Modify an existing World Link given a json object containing all the required informations.
**Please note that ID of the object is required in the JSON** + tags: + - World Links + requestBody: + description: The World Link to be modified in the world storage. + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/WorldLink' + responses: + '200': + description: OK, return the UUID of the modified World Link. + '400': + $ref: '#/components/responses/400_BadRequest' + '404': + $ref: '#/components/responses/404_NotFoundUUID' + 'default': + $ref: '#/components/responses/4xx_UnexpectedError' get: summary: Return all World Links. description: Get all the World Links currently being stored in the world storage. -- GitLab From 9bd7860fecdf74dc387229c5092f60886c3a0d51 Mon Sep 17 00:00:00 2001 From: Nathan Chambron Date: Tue, 31 May 2022 11:52:10 +0200 Subject: [PATCH 24/29] fix: chanegd version number to 1.0.0 --- API/openapi.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/API/openapi.yaml b/API/openapi.yaml index 4f710f9..5bbc3fa 100644 --- a/API/openapi.yaml +++ b/API/openapi.yaml @@ -16,7 +16,7 @@ openapi: "3.0.0" info: - version: 0.0.6 + version: 1.0.0 title: World Storage API description: API ensuring interoperability between an authoring tool and a World Storage service license: -- GitLab From 9eb75fcc39cf74c0621b3d54abf628a1b2a953ee Mon Sep 17 00:00:00 2001 From: Sylvain Renault Date: Wed, 1 Jun 2022 10:13:38 +0000 Subject: [PATCH 25/29] Update openapi.yaml --- API/openapi.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/API/openapi.yaml b/API/openapi.yaml index 5bbc3fa..c601689 100644 --- a/API/openapi.yaml +++ b/API/openapi.yaml @@ -11,7 +11,7 @@ # - Rules for RESTful error code RFC2616: https://datatracker.ietf.org/doc/html/rfc2616#section-10 # - Guide: https://restfulapi.net/http-status-codes/ # -# Last Version: 17.05.2022 +# Last Version: 01.06.2022 openapi: "3.0.0" -- GitLab From 5b1f626df42db4f8cb0fd4eba8142affda3c3af5 Mon Sep 17 00:00:00 2001 From: Nathan Chambron Date: Thu, 2 Jun 2022 12:33:31 +0000 Subject: [PATCH 26/29] remove linke size as required attribute and add typeTo and typeFrom --- API/openapi.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/API/openapi.yaml b/API/openapi.yaml index c601689..f159edf 100644 --- a/API/openapi.yaml +++ b/API/openapi.yaml @@ -513,9 +513,10 @@ components: - creatorUUID - UUIDFrom - UUIDTo + - typeFrom + - typeTo - transform - unit - - linkSize - keyvalueTags properties: UUID: -- GitLab From 53fb4d6341854e288f7d23bbdbe43929d3a7cba1 Mon Sep 17 00:00:00 2001 From: Nathan Chambron Date: Thu, 2 Jun 2022 15:20:52 +0000 Subject: [PATCH 27/29] Update responses --- API/openapi.yaml | 126 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 117 insertions(+), 9 deletions(-) diff --git a/API/openapi.yaml b/API/openapi.yaml index f159edf..0d000c5 100644 --- a/API/openapi.yaml +++ b/API/openapi.yaml @@ -42,21 +42,36 @@ paths: operationId: getPing responses: '200': - description: OK, world storage alive. + description: OK, return the UUID of the World Link defined by the world storage. + content: + text/plain: + schema: + type: string + example: "pong" /admin: get: summary: Get the state of the server. operationId: getAdmin responses: '200': - description: OK, world storage server ready. + description: OK, world storage server ready. + content: + text/plain: + schema: + type: string + example: "Server up and running" /version: get: summary: Get the version of the ARF API. operationId: getVersion responses: '200': - description: Current version. + description: Current version. + content: + text/plain: + schema: + type: string + example: "1.0.0" ############## # TRACKABLES # @@ -77,9 +92,19 @@ paths: $ref: '#/components/schemas/Trackable' responses: '200': - description: OK, return the UUID of the Trackable defined by the world storage. + description: OK, return the UUID of the Trackable defined by the world storage. + content: + text/plain: + schema: + type: string + example: "777266da-e286-11ec-8fea-0242ac120002" '201': description: Null response. + content: + text/plain: + schema: + type: string + example: "" '400': $ref: '#/components/responses/400_BadRequest' '409': @@ -102,6 +127,11 @@ paths: responses: '200': description: OK, return the UUID of the modified Trackable. + content: + text/plain: + schema: + type: string + example: "777266da-e286-11ec-8fea-0242ac120002" '400': $ref: '#/components/responses/400_BadRequest' '404': @@ -125,6 +155,11 @@ paths: $ref: "#/components/schemas/Trackable" '201': description: Null response. + content: + text/plain: + schema: + type: string + example: "" default: $ref: '#/components/responses/4xx_UnexpectedError' @@ -171,6 +206,11 @@ paths: responses: '200': description: OK, delete successful. + content: + text/plain: + schema: + type: string + example: "Element succesfully deleted" '400': $ref: '#/components/responses/400_InvalidUUID' '404': @@ -195,9 +235,19 @@ paths: $ref: '#/components/schemas/WorldAnchor' responses: '200': - description: OK, return the UUID of the World Anchor defined by the world storage. + description: OK, return the UUID of the World Anchor defined by the world storage. + content: + text/plain: + schema: + type: string + example: "777266da-e286-11ec-8fea-0242ac120002" '201': description: Null response. + content: + text/plain: + schema: + type: string + example: "" '400': $ref: '#/components/responses/400_BadRequest' '409': @@ -220,6 +270,11 @@ paths: responses: '200': description: OK, return the UUID of the modified World Anchor. + content: + text/plain: + schema: + type: string + example: "777266da-e286-11ec-8fea-0242ac120002" '400': $ref: '#/components/responses/400_BadRequest' '404': @@ -243,6 +298,11 @@ paths: $ref: "#/components/schemas/WorldAnchor" '201': description: Null response. + content: + text/plain: + schema: + type: string + example: "" default: $ref: '#/components/responses/4xx_UnexpectedError' @@ -289,6 +349,11 @@ paths: responses: '200': description: OK, delete successful. + content: + text/plain: + schema: + type: string + example: "Element succesfuly deleted" '400': $ref: '#/components/responses/400_InvalidUUID' '404': @@ -317,9 +382,15 @@ paths: content: text/plain: schema: - type: string + type: string + example: "777266da-e286-11ec-8fea-0242ac120002" '201': - description: Null response + description: Null response. + content: + text/plain: + schema: + type: string + example: "" '400': $ref: '#/components/responses/400_BadRequest' '409': @@ -342,6 +413,11 @@ paths: responses: '200': description: OK, return the UUID of the modified World Link. + content: + text/plain: + schema: + type: string + example: "777266da-e286-11ec-8fea-0242ac120002" '400': $ref: '#/components/responses/400_BadRequest' '404': @@ -364,7 +440,12 @@ paths: items : $ref: "#/components/schemas/WorldLink" '201': - description: Null response + description: Null response. + content: + text/plain: + schema: + type: string + example: "" default: $ref: '#/components/responses/4xx_UnexpectedError' @@ -410,7 +491,12 @@ paths: format: uuid responses: '200': - description: OK + description: OK, delete successful. + content: + text/plain: + schema: + type: string + example: "Element succesfully deleted" '400': $ref: '#/components/responses/400_InvalidUUID' '404': @@ -619,8 +705,10 @@ components: code: type: integer format: int32 + example: 406 message: type: string + example: "Error 406" #------------------------------- # Reusable responses @@ -643,15 +731,35 @@ components: ####################### 400_BadRequest: description: Bad request. + content: + text/plain: + schema: + type: string + example: "Bad request" 400_InvalidUUID: description: Invalid UUID supplied. + content: + text/plain: + schema: + example: "The format of the UUID is incorrect" + type: string 404_NotFoundUUID: description: Not found, could not find UUID in database. + content: + text/plain: + schema: + type: string + example: "Element not found" 409_NotEmptyUUID: description: Invalid UUID, id must be a Nil value. + content: + text/plain: + schema: + type: string + example: "The element you sent has already a value and can't be sent to the world storage" 4xx_UnexpectedError: # Can be referenced as '#/components/responses/GenericError' description: Unexpected error. -- GitLab From ddbaa791bafd0e2c7c82178e3f1dd6358a356c7e Mon Sep 17 00:00:00 2001 From: Nathan Chambron Date: Thu, 2 Jun 2022 15:36:25 +0000 Subject: [PATCH 28/29] Update openapi.yaml --- API/openapi.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/API/openapi.yaml b/API/openapi.yaml index 0d000c5..e4f8e33 100644 --- a/API/openapi.yaml +++ b/API/openapi.yaml @@ -42,7 +42,7 @@ paths: operationId: getPing responses: '200': - description: OK, return the UUID of the World Link defined by the world storage. + description: Ok, returns a string message content: text/plain: schema: -- GitLab From 29f887a0f940e999d32bc27fe9bec1bdf54d986c Mon Sep 17 00:00:00 2001 From: Sylvain Renault Date: Thu, 2 Jun 2022 15:39:24 +0000 Subject: [PATCH 29/29] Update openapi.yaml --- API/openapi.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/API/openapi.yaml b/API/openapi.yaml index e4f8e33..0b4e4f0 100644 --- a/API/openapi.yaml +++ b/API/openapi.yaml @@ -38,11 +38,11 @@ tags: paths: /ping: get: - summary: Test the server availability + summary: Test the server availability. operationId: getPing responses: '200': - description: Ok, returns a string message + description: Ok, returns a string message. content: text/plain: schema: -- GitLab