diff --git a/alfalfa_web/api.yml b/alfalfa_web/api.yml new file mode 100644 index 00000000..c6b3470a --- /dev/null +++ b/alfalfa_web/api.yml @@ -0,0 +1,765 @@ +openapi: "3.0.2" +info: + title: Alfalfa-BOPTEST Unified Virtual Building Control API (ABUVBCAPI) + version: "1.0" + description: > + A REST API for controlling virtual buildings. + A collaboration between the [Alfalfa](https://github.com/nrel/alfalfa) + and [BOPTEST](https://github.com/ibpsa/project1-boptest) projects. +tags: + - name: Point + description: Reading, Writing, and Listing Points + - name: Run + description: Creating, Interacting, and Destroying Runs + - name: Model + description: Creating, and Downloading Models +servers: + - url: https://api.server.test/v1 +paths: + /runs: + get: + summary: List Runs + tags: + - "Run" + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + payload: + type: array + items: + $ref: "#/components/schemas/runMetadata" + /runs/{runId}: + get: + summary: Get run metadata + parameters: + - $ref: "#/components/parameters/runId" + tags: + - "Run" + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + payload: + $ref: "#/components/schemas/runMetadata" + delete: + summary: Delete run + parameters: + - $ref: "#/components/parameters/runId" + tags: + - "Run" + responses: + 204: + description: The run was deleted + /runs/{runId}/time: + get: + summary: Get simulation time + tags: + - Run + parameters: + - $ref: "#/components/parameters/runId" + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + payload: + type: string + format: "date-time" + /runs/{runId}/start: + post: + summary: Start a Run + tags: + - Run + parameters: + - $ref: "#/components/parameters/runId" + requestBody: + content: + application/json: + schema: + type: object + properties: + startDatetime: + type: string + format: "date-time" + description: "Start Time" + endDatetime: + type: string + format: "date-time" + description: "End Time" + timescale: + type: number + example: 1 + description: "Time multiplier determining simulation speed" + externalClock: + type: boolean + example: true + description: "When true the Run will only advance when triggered via the API" + realtime: + type: boolean + example: false + description: "Simulate the model in realtime" + required: + - startDatetime + - endDatetime + responses: + 204: + description: The run was started + /runs/{runId}/advance: + post: + summary: Advance run by one timestep + tags: + - Run + parameters: + - $ref: "#/components/parameters/runId" + responses: + 204: + description: Run was advanced + /runs/{runId}/stop: + post: + summary: Stop a Run + tags: + - Run + parameters: + - $ref: "#/components/parameters/runId" + responses: + 204: + description: The run was stopped + /runs/{runId}/download: + get: + description: Download run by redirecting to the S3 tarball url + tags: + - Run + parameters: + - $ref: "#/components/parameters/runId" + responses: + 302: + description: Download response + headers: + Location: + schema: + type: string + format: url + content: + application/octet-stream: + schema: + type: string + format: binary + /runs/{runId}/points: + get: + summary: Get metadata for all points + tags: + - Point + parameters: + - $ref: "#/components/parameters/runId" + responses: + "200": + description: OK + content: + application/json: + schema: + type: object + properties: + payload: + type: array + items: + $ref: "#/components/schemas/pointMetadata" + message: + $ref: "#/components/schemas/responseMessage" + required: + - payload + post: + summary: Get metadata for multiple points + tags: + - Point + parameters: + - $ref: "#/components/parameters/runId" + requestBody: + content: + application/json: + schema: + oneOf: + - type: object + properties: + points: + type: array + items: + $ref: "#/components/schemas/pointId" + - type: object + properties: + pointTypes: + type: array + items: + $ref: "#/components/schemas/pointType" + examples: + Points: + value: + points: + - AHU1_Mixed_Air_Temperature_Sensor + - Outdoor_Air_Temperature_Sensor + Point Types: + value: + pointTypes: + - "output" + responses: + 200: + description: "OK" + content: + application/json: + schema: + type: object + properties: + payload: + type: array + items: + $ref: "#/components/schemas/pointMetadata" + message: + $ref: "#/components/schemas/responseMessage" + required: + - payload + 400: + description: Cannot retrieve points due to invalid request + content: + application/json: + schema: + $ref: "#/components/schemas/errorResponse" + example: + message: "Could not retrieve points due to invalid request" + payload: + - "Point 'AHU7_Mixed_Air_Temperature' does not exist" + /runs/{runId}/points/{pointId}: + get: + summary: Get metadata and value for single point + tags: + - Point + parameters: + - $ref: "#/components/parameters/runId" + - $ref: "#/components/parameters/pointId" + responses: + "200": + description: OK + content: + application/json: + schema: + type: object + properties: + payload: + $ref: "#/components/schemas/pointData" + message: + $ref: "#/components/schemas/responseMessage" + required: + - payload + put: + summary: Set value for single point + tags: + - Point + parameters: + - $ref: "#/components/parameters/runId" + - $ref: "#/components/parameters/pointId" + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/pointValue" + responses: + 204: + description: The point was successfully updated + 400: + description: The point could not be written to due to an invalid request + content: + application/json: + schema: + $ref: "#/components/schemas/errorResponse" + example: + message: "Point is of type 'OUTPUT' and cannot be written to" + /runs/{runId}/points/values: + get: + summary: Get values for all points + tags: + - Point + parameters: + - $ref: "#/components/parameters/runId" + responses: + 200: + description: "OK" + content: + application/json: + schema: + type: object + properties: + payload: + type: object + additionalProperties: true + message: + $ref: "#/components/schemas/responseMessage" + required: + - payload + example: + payload: + Supply_Air_Temperature_Sensor: 25.3 + Outdoor_Air_Temperature_Sensor: 30.5 + post: + summary: Get values for multiple points + tags: + - Point + parameters: + - $ref: "#/components/parameters/runId" + requestBody: + content: + application/json: + schema: + oneOf: + - type: object + properties: + points: + type: array + items: + $ref: "#/components/schemas/pointId" + - type: object + properties: + pointTypes: + type: array + items: + $ref: "#/components/schemas/pointType" + examples: + Points: + value: + points: + - Supply_Air_Temperature_Setpoint + - Outdoor_Air_Temperature_Sensor + Point Types: + value: + pointTypes: + - "output" + responses: + 200: + description: "OK" + content: + application/json: + schema: + type: object + properties: + payload: + type: object + additionalProperties: true + message: + $ref: "#/components/schemas/responseMessage" + example: + payload: + Supply_Air_Temperature_Sensor: 25.3 + Outdoor_Air_Temperature_Sensor: 30.5 + 400: + description: "Points could not be read due to improper request" + content: + application/json: + schema: + $ref: "#/components/schemas/errorResponse" + example: + message: "Request contained invalid read requests" + payload: + - "Point 'Supply_Air_Temperature_Setpoint' does not exist" + - "Point 'AHU1_Outdoor_Air_Damper_Position' is of type 'INPUT' and cannot be read" + put: + summary: Set new values for multiple points + tags: + - Point + parameters: + - $ref: "#/components/parameters/runId" + requestBody: + content: + application/json: + schema: + type: object + additionalProperties: true + example: + Supply_Air_Temperature_Setpoint: 23.1 + AHU1_Outdoor_Air_Damper_Position: 0.6 + AHU1_Economizing_Mode: 2 + responses: + 204: + description: "Points successfully updated" + 400: + description: "Points could not be updated due to improper request" + content: + application/json: + schema: + $ref: "#/components/schemas/errorResponse" + example: + message: "Request contained invalid write requests" + payload: + - "Point 'Supply_Air_Temperature_Setpoint' does not exist" + - "Point 'Outdoor_Air_Temperature_Sensor' is of type 'OUTPUT' and cannot be written to" + /aliases: + get: + description: List aliases + tags: + - Alias + responses: + 200: + description: Aliases response + content: + application/json: + schema: + type: object + additionalProperties: + $ref: "#/components/schemas/runId" + example: + foo: d4e2c041-0389-4933-8aa4-016d80283779 + bar: 9e2acb8e-974e-406b-a990-48e9743b01de + /aliases/{alias}: + put: + description: Create or update an alias to point to a Run + tags: + - Alias + parameters: + - $ref: "#/components/parameters/aliasName" + responses: + 204: + description: The alias was set successfully + get: + description: Get alias + tags: + - Alias + parameters: + - $ref: "#/components/parameters/aliasName" + responses: + "200": + description: Alias response + content: + application/json: + schema: + type: object + properties: + payload: + $ref: "#/components/schemas/runId" + example: + payload: 4b8c6b40-f818-11ec-a8bd-75570e3e3a28 + delete: + description: Delete alias + tags: + - Alias + parameters: + - $ref: "#/components/parameters/aliasName" + responses: + 204: + description: The alias was deleted + /models: + get: + description: List models + tags: + - Model + responses: + 200: + description: Models response + content: + application/json: + schema: + type: object + properties: + payload: + type: array + items: + $ref: "#/components/schemas/modelMetadata" + example: + payload: + - id: 4b8c6b40-f818-11ec-a8bd-75570e3e3a28 + modelName: refrig_case_osw.zip + created: 2023-03-09T17:49:13.742Z + modified: 2023-03-09T17:49:13.742Z + - id: 82ae8d50-f837-11ec-bda1-355419177ef9 + modelName: refrig_case_osw_2.zip + created: 2023-03-09T17:49:13.742Z + modified: 2023-03-09T17:49:13.742Z + /models/upload: + post: + description: Create a POST url to upload a model + tags: + - Model + requestBody: + content: + application/json: + schema: + type: object + properties: + modelName: + type: string + description: Upload filename + example: my_model.zip + required: + - modelName + responses: + 200: + description: Upload response + content: + application/json: + schema: + type: object + properties: + url: + type: string + format: url + fields: + type: object + properties: + bucket: + type: string + X-Amz-Algorithm: + type: string + X-Amz-Credential: + type: string + X-Amz-Date: + type: string + key: + type: string + Policy: + type: string + X-Amz-Signature: + type: string + modelId: + $ref: "#/components/schemas/modelId" + example: + url: http://alfalfa.lan:9000/alfalfa + fields: + bucket: alfalfa + X-Amz-Algorithm: AWS4-HMAC-SHA256 + X-Amz-Credential: AKIA4MRT6LFGGPHNCKOO/20230309/us-west-1/s3/aws4_request + X-Amz-Date: 20230309T200246Z + key: uploads/5c1a0300-beb5-11ed-8531-d9fb035ab2f0/my_model.zip + Policy: eyJleHBpcmF0aW9uIjoiMjAyMy0wMy0wOVQyMTowMjo0NloiLCJjb25kaXRpb25zIjpbeyJidWNrZXQiOiJhbGZhbGZhIn0seyJYLUFtei1BbGdvcml0aG0iOiJBV1M0LUhNQUMtU0hBMjU2In0seyJYLUFtei1DcmVkZW50aWFsIjoiQUtJQTRNUlQ2TEZHR1BITkNLT08vMjAyMzAzMDkvdXMtd2VzdC0xL3MzL2F3czRfcmVxdWVzdCJ9LHsiWC1BbXotRGF0ZSI6IjIwMjMwMzA5VDIwMDI0NloifSx7ImtleSI6InVwbG9hZHMvNWMxYTAzMDAtYmViNS0xMWVkLTg1MzEtZDlmYjAzNWFiMmYwL215X21vZGVsLnppcCJ9XX0= + X-Amz-Signature: 7d09a673e65112ee06c7666c34eb9c4ca13cc43f285efc9c1c497befd3a64343 + modelId: 5c1a0300-beb5-11ed-8531-d9fb035ab2f0 + /models/{modelId}/createRun: + post: + description: Create a Run from a model + tags: + - Model + parameters: + - $ref: "#/components/parameters/modelId" + responses: + 200: + description: Create run response + content: + application/json: + schema: + type: object + properties: + payload: + type: object + properties: + runId: + $ref: "#/components/schemas/runId" + example: + payload: + runId: 28f76e90-bef6-11ed-822a-e3558db4daaf + /models/{modelId}/download: + get: + description: Download a model by redirecting to the S3 tarball url + tags: + - Model + parameters: + - $ref: "#/components/schemas/modelId" + responses: + 302: + description: Download response + headers: + Location: + schema: + type: string + format: url + content: + application/octet-stream: + schema: + type: string + format: binary + /version: + get: + description: Return the Alfalfa version and git SHA + tags: + - About + responses: + 200: + description: Version response + content: + application/json: + schema: + type: object + properties: + payload: + type: object + properties: + version: + type: string + example: "0.7.0" + sha: + type: string + example: "c90d0641cb" +components: + schemas: + runId: + type: string + example: 7cf4afb6-9c15-431f-9f50-11bca0870f77 + pointId: + type: string + example: Outdoor_Air_Temperature_Sensor + pointName: + type: string + example: Outdoor Air Temperature Sensor + pointType: + type: string + enum: + - "INPUT" + - "OUTPUT" + - "BIDIRECTIONAL" + runStatus: + type: string + enum: + - "CREATED" + - "PREPROCESSING" + - "READY" + - "STARTING" + - "STARTED" + - "RUNNING" + - "STOPPING" + - "COMPLETE" + - "ERROR" + simType: + type: string + enum: + - "OPENSTUDIO" + - "MODELICA" + - "OTHER" + runMetadata: + type: object + properties: + id: + $ref: "#/components/schemas/runId" + name: + type: string + example: "Run Name" + status: + $ref: "#/components/schemas/runStatus" + datetime: + type: string + format: "date-time" + simType: + $ref: "#/components/schemas/simType" + uploadTimestamp: + type: string + format: "date-time" + errorLog: + type: "string" + example: "An unknown error occurred. Good luck!" + pointDataType: + type: string + enum: + - "float" + - "int" + - "bool" + default: "float" + pointMetadata: + type: object + properties: + id: + $ref: "#/components/schemas/pointId" + name: + $ref: "#/components/schemas/pointName" + description: + type: string + example: An outdoor air temperature sensor for an air handling unit + readOnly: true + unit: + type: string + example: °F + readOnly: true + min: + type: number + readOnly: true + max: + type: number + readOnly: true + type: + $ref: "#/components/schemas/pointType" + dataType: + $ref: "#/components/schemas/pointDataType" + required: + - id + - type + pointValue: + type: object + properties: + value: + type: number + example: 24.3 + pointData: + allOf: + - $ref: "#/components/schemas/pointMetadata" + - $ref: "#/components/schemas/pointValue" + errorResponse: + type: object + properties: + message: + $ref: "#/components/schemas/responseMessage" + payload: {} + required: + - message + responseMessage: + type: string + example: Placeholder human readable message about what happened. + aliasName: + type: string + modelId: + type: string + format: uuid + modelMetadata: + type: object + properties: + id: + $ref: "#/components/schemas/modelId" + model_name: + type: string + created: + type: string + format: "date-time" + modified: + type: string + format: "date-time" + parameters: + runId: + in: path + name: runId + schema: + $ref: "#/components/schemas/runId" + required: true + description: ID of run + pointId: + in: path + name: pointId + schema: + $ref: "#/components/schemas/pointId" + required: true + description: ID of point + aliasName: + in: path + name: alias + schema: + $ref: "#/components/schemas/aliasName" + required: true + description: Name of an alias + modelId: + in: path + name: modelId + schema: + $ref: "#/components/schemas/modelId" + required: true + description: ID of model diff --git a/alfalfa_web/components.yml b/alfalfa_web/components.yml deleted file mode 100644 index 95e9cf84..00000000 --- a/alfalfa_web/components.yml +++ /dev/null @@ -1,73 +0,0 @@ -components: - schemas: - runId: - type: string - pointId: - type: string - format: uuid - pointName: - type: string - default: Outdoor Air Temperature Sensor - pointType: - type: string - enum: - - "input" - - "output" - - "bidirectional" - runMetadata: - type: object - properties: - id: - $ref: "#/components/schemas/runId" - pointMetadata: - type: object - properties: - id: - $ref: "#/components/schemas/pointId" - name: - $ref: "#/components/schemas/pointName" - description: - type: string - default: An outdoor air temperature sensor for an air handling unit - readOnly: true - unit: - type: string - default: °F - readOnly: true - min: - type: number - readOnly: true - max: - type: number - type: - $ref: "#/components/schemas/pointType" - required: - - id - - type - pointValue: - type: object - properties: - id: - $ref: "#/components/schemas/pointId" - value: - type: number - default: 24.3 - pointData: - allOf: - - $ref: "#/components/schemas/pointMetadata" - - $ref: "#/components/schemas/pointValue" - parameters: - runId: - in: path - name: runId - schema: - $ref: "#/components/schemas/runId" - required: true - description: UUID of run - pointId: - in: path - name: pointId - schema: - $ref: "#/components/schemas/pointId" - required: true - description: UUID of point diff --git a/alfalfa_web/generate-docs.js b/alfalfa_web/generate-docs.js index 78eee792..a149f312 100644 --- a/alfalfa_web/generate-docs.js +++ b/alfalfa_web/generate-docs.js @@ -8,7 +8,7 @@ const { version } = require("./package.json"); const serverType = process.env.NODE_ENV === "production" ? "Production" : "Development"; const openapiSpecification = swaggerJsdoc({ - apis: ["./server/api-v2.js", "./server/api-haystack.js", "./components.yml"], + apis: ["./server/api-v2.js", "./server/api-haystack.js", "./api.yml"], definition: { openapi: "3.1.0", info: { @@ -33,23 +33,19 @@ const openapiSpecification = swaggerJsdoc({ }, { name: "Alias", - description: "Manage site id aliases" + description: "Creating and Accessing Aliases for Runs" }, { name: "Model", - description: "Manage models" + description: "Creating, and Downloading Models" }, { - name: "Simulation", - description: "Manage completed simulations, including any that may have stopped with errors" - }, - { - name: "Site", - description: "Manage sites" + name: "Run", + description: "Creating, Interacting, and Destroying Runs" }, { - name: "Run", - description: "Manage Runs" + name: "Point", + description: "Reading, Writing, and Listing Points" }, { name: "Haystack", @@ -60,191 +56,13 @@ const openapiSpecification = swaggerJsdoc({ "x-tagGroups": [ { name: "Alfalfa API", - tags: ["About", "Alias", "Model", "Simulation", "Site", "Run"] + tags: ["About", "Model", "Run", "Point", "Alias"] }, { name: "Project Haystack API", tags: ["Haystack"] } - ], - components: { - parameters: { - Alias: { - name: "alias", - in: "path", - description: "Alias name", - required: true, - schema: { - type: "string" - } - }, - ModelID: { - name: "modelId", - in: "path", - description: "Model ID", - required: true, - schema: { - type: "string", - format: "uuid" - } - }, - PointID: { - name: "pointId", - in: "path", - description: "Point ID", - required: true, - schema: { - type: "string", - format: "uuid" - } - }, - SiteID: { - name: "siteId", - in: "path", - description: "Site ID", - required: true, - schema: { - type: "string", - format: "uuid" - } - } - }, - schemas: { - Error: { - type: "object", - properties: { - error: { - type: "string", - description: "Error message", - example: "Something went wrong" - } - } - }, - Model: { - type: "object", - properties: { - id: { - type: "string", - format: "uuid" - }, - modelName: { - type: "string" - }, - created: { - type: "string", - format: "date-time" - }, - modified: { - type: "string", - format: "date-time" - } - } - }, - Point: { - type: "object", - properties: { - id: { - type: "string", - format: "uuid" - }, - name: { - type: "string" - }, - type: { - type: "string", - enum: ["INPUT", "OUTPUT", "BIDIRECTIONAL"] - }, - value: { - type: "float", - description: - "Value is only returned for `OUTPUT` and `BIDIRECTIONAL` points if available. Values are not returned when using the `/points/inputs` endpoint" - } - }, - required: ["id", "name", "type"] - }, - Simulation: { - type: "object", - properties: { - id: { - type: "string", - format: "uuid" - }, - name: { - type: "string" - }, - timeCompleted: { - type: "string", - format: "date-time" - }, - status: { - type: "string", - enum: ["complete", "error"] - }, - url: { - type: "string" - }, - results: { - type: "object" - } - } - }, - Site: { - type: "object", - properties: { - id: { - type: "string", - format: "uuid" - }, - name: { - type: "string" - }, - status: { - type: "string", - enum: [ - "created", - "preprocessing", - "ready", - "starting", - "started", - "running", - "stopping", - "complete", - "error" - ] - }, - simType: { - type: "string" - }, - datetime: { - type: "string" - }, - uploadTimestamp: { - type: "string", - format: "date-time" - }, - uploadPath: { - type: "string" - }, - errorLog: { - type: "string" - } - } - }, - Version: { - type: "object", - properties: { - version: { - type: "string", - description: "The current Alfalfa release version" - }, - sha: { - type: "string", - description: "The git SHA of Alfalfa that is deployed" - } - } - } - } - } + ] } }); diff --git a/alfalfa_web/server/api-v2.js b/alfalfa_web/server/api-v2.js index e74b107d..0a4f1b0b 100644 --- a/alfalfa_web/server/api-v2.js +++ b/alfalfa_web/server/api-v2.js @@ -48,45 +48,6 @@ router.get(/\/$/, (req, res) => { res.redirect(301, `${route}${req.url.slice(0, -1)}`); }); -/** - * @openapi - * /runs: - * get: - * operationId: List runs - * description: Return list of runs - * tags: - * - Run - * responses: - * 200: - * description: Runs response - * content: - * application/json: - * schema: - * type: object - * properties: - * data: - * type: array - * items: - * $ref: '#/components/schemas/Site' - * example: - * data: - * - id: 4b8c6b40-f818-11ec-a8bd-75570e3e3a28 - * name: Building 1 - * status: complete - * simType: osm - * datetime: 2022-03-15 00:00:00 - * uploadTimestamp: 2022-03-15T14:55:27.131Z - * uploadPath: uploads/6b3ddba0-c341-11ed-974b-bf90e67a18f9/refrig_case_osw.zip - * errorLog: '' - * - id: 82ae8d50-f837-11ec-bda1-355419177ef9 - * name: Building 2 - * status: ready - * simType: osm - * datetime: '' - * uploadTimestamp: 2022-06-30T05:43:06.885Z - * uploadPath: uploads/82ae8d50-f837-11ec-bda1-355419177ef9/refrig_case_osw_2.zip - * errorLog: '' - */ router.get("/runs", async (req, res, next) => { api .listRuns() @@ -187,39 +148,6 @@ router.param("modelId", (req, res, next, id) => { .catch(next); }); -/** - * @openapi - * /runs/{runId}: - * get: - * operationId: Get run - * description: Lookup a run by id - * tags: - * - Run - * parameters: - * - $ref: '#/components/parameters/SiteID' - * responses: - * 200: - * description: Run response - * content: - * application/json: - * schema: - * type: object - * properties: - * data: - * $ref: '#/components/schemas/Site' - * example: - * data: - * id: 4b8c6b40-f818-11ec-a8bd-75570e3e3a28 - * name: Building 1 - * uploadTimestamp: 2022-06-30T05:43:06.885Z - * uploadPath: uploads/4b8c6b40-f818-11ec-a8bd-75570e3e3a28/refrig_case_osw.zip - * 404: - * description: Run ID does not exist - * content: - * application/json: - * schema: - * $ref: '#/components/schemas/Error' - */ router.get("/runs/:runId", async (req, res, next) => { api .formatRun(req.run) @@ -229,29 +157,6 @@ router.get("/runs/:runId", async (req, res, next) => { .catch(next); }); -/** - * @openapi - * /runs/{runId}/time: - * get: - * operationId: Get simulation time - * description: Return the current time of the simulation if it has been started - * tags: - * - Run - * parameters: - * - $ref: '#/components/parameters/runId' - * responses: - * 200: - * description: Time response - * content: - * application/json: - * schema: - * type: object - * properties: - * time: - * type: string - * example: - * time: 2022-06-15 00:00:00 - */ router.get("/runs/:runId/time", async (req, res, next) => { api .getRunTime(req.run) @@ -259,25 +164,6 @@ router.get("/runs/:runId/time", async (req, res, next) => { .catch(next); }); -/** - * @openapi - * /runs/{runId}/points: - * get: - * summary: Get the metadata for all points of an associated run - * tags: - * - Run - * parameters: - * - $ref: '#/components/parameters/runId' - * responses: - * '200': - * description: OK - * content: - * application/json: - * schema: - * type: array - * items: - * $ref: '#/components/schemas/pointMetadata' - */ router.get("/runs/:runId/points", (req, res, next) => { api .getPointsByRun(req.run) @@ -290,52 +176,6 @@ router.get("/runs/:runId/points", (req, res, next) => { .catch(next); }); -/** - * @openapi - * /runs/{runId}/points: - * post: - * summary: Get metadata for specific points - * tags: - * - Run - * parameters: - * - $ref: '#/components/parameters/runId' - * requestBody: - * content: - * application/json: - * schema: - * oneOf: - * - type: object - * properties: - * points: - * type: array - * items: - * $ref: '#/components/schemas/pointId' - * - type: object - * properties: - * pointTypes: - * type: array - * items: - * $ref: '#/components/schemas/pointType' - * examples: - * Points: - * value: - * points: - * - 7cf4afb6-9c15-431f-9f50-11bca0870f77 - * - Outdoor Air Temperature Sensor - * Point Types: - * value: - * pointTypes: - * - 'output' - * responses: - * 200: - * description: 'OK' - * content: - * application/json: - * schema: - * type: array - * items: - * $ref: '#/components/schemas/pointMetadata' - */ router.post("/runs/:runId/points", async (req, res, next) => { const { points, pointTypes } = req.body; @@ -356,25 +196,6 @@ router.post("/runs/:runId/points", async (req, res, next) => { .catch(next); }); -/** - * @openapi - * /runs/{runId}/points/values: - * get: - * summary: Get values for all points - * tags: - * - Run - * parameters: - * - $ref: '#/components/parameters/runId' - * responses: - * 200: - * description: 'OK' - * content: - * application/json: - * schema: - * type: array - * items: - * $ref: '#/components/schemas/pointValue' - */ router.get("/runs/:runId/points/values", (req, res, next) => { api .getPointsByType(req.run, ["OUTPUT", "BIDIRECTIONAL"]) @@ -393,52 +214,6 @@ router.get("/runs/:runId/points/values", (req, res, next) => { .catch(next); }); -/** - * @openapi - * /runs/{runId}/points/values: - * post: - * summary: Get values for specific points - * tags: - * - Run - * parameters: - * - $ref: '#/components/parameters/runId' - * requestBody: - * content: - * application/json: - * schema: - * oneOf: - * - type: object - * properties: - * points: - * type: array - * items: - * $ref: '#/components/schemas/pointId' - * - type: object - * properties: - * pointTypes: - * type: array - * items: - * $ref: '#/components/schemas/pointType' - * examples: - * Points: - * value: - * points: - * - 7cf4afb6-9c15-431f-9f50-11bca0870f77 - * - Outdoor Air Temperature Sensor - * Point Types: - * value: - * pointTypes: - * - 'output' - * responses: - * 200: - * description: 'OK' - * content: - * application/json: - * schema: - * type: array - * items: - * $ref: '#/components/schemas/pointValue' - */ router.post("/runs/:runId/points/values", async (req, res, next) => { const { points, pointTypes } = req.body; @@ -461,45 +236,6 @@ router.post("/runs/:runId/points/values", async (req, res, next) => { res.status(200).json({ payload }); }); -/** - * @openapi - * /runs/{runId}/points/values: - * put: - * summary: Put new values to specified points - * tags: - * - points - * - runs - * parameters: - * - $ref: 'components.yml#/components/parameters/runId' - * requestBody: - * content: - * application/json: - * schema: - * type: array - * items: - * $ref: 'components.yml#/components/schemas/pointValue' - * example: - * - id: 7cf4afb6-9c15-431f-9f50-11bca0870f77 - * value: 7.0 - * - id: 76d43bc5-9c56-48a8-b9e5-61a651b8dee4 - * value: 12.6 - * - id: 58b717ad-20a7-4cc6-89f1-f99b1938b0ef - * value: 0.5 - * responses: - * 200: - * description: 'Points successfully updated' - * content: - * application/json: - * schema: - * type: object - * properties: - * success: - * type: boolean - * errors: - * type: array - * items: - * type: string - */ router.put("/runs/:runId/points/values", async (req, res, next) => { const { points } = req.body; @@ -540,24 +276,6 @@ router.put("/runs/:runId/points/values", async (req, res, next) => { } }); -/** - * @openapi - * /runs/{runId}/points/{pointId}: - * get: - * summary: Get data for point of a given ID - * tags: - * - Run - * parameters: - * - $ref: '#/components/parameters/runId' - * - $ref: '#/components/parameters/pointId' - * responses: - * '200': - * description: OK - * content: - * application/json: - * schema: - * $ref: '#/components/schemas/pointData' - */ router.get("/runs/:runId/points/:pointId", (req, res, next) => { if (req.point.point_type != "INPUT") { api @@ -573,25 +291,6 @@ router.get("/runs/:runId/points/:pointId", (req, res, next) => { } }); -/** - * @openapi - * /runs/{runId}/points/{pointId}: - * put: - * summary: Set value for point of given ID - * tags: - * - Run - * parameters: - * - $ref: '#/components/parameters/runId' - * - $ref: '#/components/parameters/pointId' - * requestBody: - * content: - * application/json: - * schema: - * $ref: '#/components/schemas/pointValue' - * responses: - * 204: - * description: The point was successfully updated - */ router.put("/runs/:runId/points/:pointId", (req, res, next) => { const { value } = req.body; @@ -617,25 +316,6 @@ router.put("/runs/:runId/points/:pointId", (req, res, next) => { .catch(next); }); -/** - * @openapi - * /runs/{runId}: - * delete: - * operationId: Delete run - * tags: - * - Run - * parameters: - * - $ref: '#/components/parameters/runId' - * responses: - * 204: - * description: The run was deleted successfully - * 404: - * description: Run ID does not exist - * content: - * application/json: - * schema: - * $ref: '#/components/schemas/Error' - */ router.delete("/runs/:runId", (req, res, next) => { api .removeRun(req.run) @@ -645,55 +325,6 @@ router.delete("/runs/:runId", (req, res, next) => { .catch(next); }); -/** - * @openapi - * /runs/{runId}/start: - * post: - * operationId: Start run - * description: Start a run - * tags: - * - Run - * parameters: - * - $ref: '#/components/parameters/runId' - * requestBody: - * content: - * application/json: - * schema: - * type: object - * properties: - * startDatetime: - * type: string - * description: Start Time - * example: 2022-06-30 12:00:00 - * endDatetime: - * type: string - * description: End Time - * example: 2022-06-30 12:10:00 - * timescale: - * type: number - * description: Time multiplier determining simulation speed - * example: 5 - * externalClock: - * type: boolean - * description: The run will only advance when explicitly told to via an external call - * example: false - * realtime: - * type: boolean - * description: Simulate the model in realtime - * example: false - * required: - * - startDatetime - * - endDatetime - * responses: - * 204: - * description: The run was started successfully - * 404: - * description: Run ID does not exist - * content: - * application/json: - * schema: - * $ref: '#/components/schemas/Error' - */ router.post("/runs/:runId/start", (req, res, next) => { const { body } = req; @@ -733,26 +364,6 @@ router.post("/runs/:runId/start", (req, res, next) => { .catch(next); }); -/** - * @openapi - * /runs/{runId}/advance: - * post: - * operationId: Advance run - * description: Advances a run by one minute - * tags: - * - Run - * parameters: - * - $ref: '#/components/parameters/runId' - * responses: - * 204: - * description: The run was advanced successfully - * 404: - * description: Run ID does not exist - * content: - * application/json: - * schema: - * $ref: '#/components/schemas/Error' - */ router.post("/runs/:runId/advance", (req, res, next) => { api .advanceRun(req.run) @@ -762,26 +373,6 @@ router.post("/runs/:runId/advance", (req, res, next) => { .catch(next); }); -/** - * @openapi - * /runs/{runId}/stop: - * post: - * operationId: Stop run - * description: Stop a run - * tags: - * - Run - * parameters: - * - $ref: '#/components/parameters/runId' - * responses: - * 204: - * description: The run was stopped successfully - * 404: - * description: Run ID does not exist - * content: - * application/json: - * schema: - * $ref: '#/components/schemas/Error' - */ router.post("/runs/:runId/stop", (req, res, next) => { // If the run is already stopping or stopped there is no need to send message if (["STOPPING", "COMPLETE", "ERROR", "READY"].includes(req.run.status)) { @@ -795,30 +386,6 @@ router.post("/runs/:runId/stop", (req, res, next) => { .catch(next); }); -/** - * @openapi - * /runs/{runId}/download: - * get: - * operationId: Download run - * description: Download run by redirecting to the S3 tarball url - * tags: - * - Run - * parameters: - * - $ref: '#/components/parameters/runId' - * responses: - * 302: - * description: Download response - * headers: - * Location: - * schema: - * type: string - * format: url - * content: - * application/octet-stream: - * schema: - * type: string - * format: binary - */ router.get("/runs/:runId/download", (req, res, next) => { api .getRunDownloadPath(req.run) @@ -828,28 +395,6 @@ router.get("/runs/:runId/download", (req, res, next) => { .catch(next); }); -/** - * @openapi - * /aliases: - * get: - * operationId: List aliases - * description: Return list of aliases - * tags: - * - Alias - * responses: - * 200: - * description: Aliases response - * content: - * application/json: - * schema: - * type: object - * additionalProperties: - * type: string - * format: uuid - * example: - * foo: d4e2c041-0389-4933-8aa4-016d80283779 - * bar: 9e2acb8e-974e-406b-a990-48e9743b01de - */ router.get("/aliases", (req, res, next) => { api .listAliases() @@ -857,26 +402,6 @@ router.get("/aliases", (req, res, next) => { .catch(next); }); -/** - * @openapi - * /aliases/{alias}: - * put: - * operationId: Set alias - * description: Create or update an alias to point to a run id - * tags: - * - Alias - * parameters: - * - $ref: '#/components/parameters/Alias' - * responses: - * 204: - * description: The alias was set successfully - * 404: - * description: Run ID does not exist - * content: - * application/json: - * schema: - * $ref: '#/components/schemas/Error' - */ router.put("/aliases/:alias", async (req, res, next) => { const { alias } = req.params; const { runId } = req.body; @@ -931,55 +456,10 @@ router.all("/aliases/:alias", (req, res, next) => { .catch(next); }); -/** - * @openapi - * /aliases/{alias}: - * get: - * operationId: Get alias - * description: Lookup the run id of an alias - * tags: - * - Alias - * parameters: - * - $ref: '#/components/parameters/Alias' - * responses: - * 200: - * description: Alias response - * content: - * application/json: - * schema: - * type: string - * example: - * 4b8c6b40-f818-11ec-a8bd-75570e3e3a28 - * 404: - * description: Alias does not exist - * content: - * application/json: - * schema: - * $ref: '#/components/schemas/Error' - */ router.get("/aliases/:alias", (req, res) => { res.json({ payload: req.run.ref_id }); }); -/** - * @openapi - * /aliases/{alias}: - * delete: - * operationId: Delete alias - * tags: - * - Alias - * parameters: - * - $ref: '#/components/parameters/Alias' - * responses: - * 204: - * description: The alias was deleted successfully - * 404: - * description: Alias does not exist - * content: - * application/json: - * schema: - * $ref: '#/components/schemas/Error' - */ router.delete("/aliases/:alias", (req, res, next) => { api .removeAlias(req.alias) @@ -989,25 +469,6 @@ router.delete("/aliases/:alias", (req, res, next) => { .catch(next); }); -/** - * @openapi - * /version: - * get: - * operationId: Alfalfa version - * description: Return the Alfalfa version and git SHA - * tags: - * - About - * responses: - * 200: - * description: Version response - * content: - * application/json: - * schema: - * $ref: '#/components/schemas/Version' - * example: - * version: 0.4.0 - * sha: c90d0641cb - */ router.get("/version", (req, res) => { let sha = {}; const shaPath = path.resolve(__dirname, "./sha.json"); @@ -1017,37 +478,6 @@ router.get("/version", (req, res) => { res.json({ payload: { version, ...sha } }); }); -/** - * @openapi - * /models: - * get: - * operationId: List models - * description: Return list of models - * tags: - * - Model - * responses: - * 200: - * description: Models response - * content: - * application/json: - * schema: - * type: object - * properties: - * data: - * type: array - * items: - * $ref: '#/components/schemas/Model' - * example: - * data: - * - id: 4b8c6b40-f818-11ec-a8bd-75570e3e3a28 - * modelName: refrig_case_osw.zip - * created: 2023-03-09T17:49:13.742Z - * modified: 2023-03-09T17:49:13.742Z - * - id: 82ae8d50-f837-11ec-bda1-355419177ef9 - * modelName: refrig_case_osw_2.zip - * created: 2023-03-09T17:49:36.004Z - * modified: 2023-03-09T17:49:36.004Z - */ router.get("/models", async (req, res, next) => { api .listModels() @@ -1055,68 +485,6 @@ router.get("/models", async (req, res, next) => { .catch(next); }); -/** - * @openapi - * /models/upload: - * post: - * operationId: Model upload url - * description: Create a POST url to upload a model - * tags: - * - Model - * requestBody: - * content: - * application/json: - * schema: - * type: object - * properties: - * modelName: - * type: string - * description: Upload filename - * example: my_model.zip - * required: - * - modelName - * responses: - * 200: - * description: Upload response - * content: - * application/json: - * schema: - * type: object - * properties: - * url: - * type: string - * fields: - * type: object - * properties: - * bucket: - * type: string - * X-Amz-Algorithm: - * type: string - * X-Amz-Credential: - * type: string - * X-Amz-Date: - * type: string - * key: - * type: string - * Policy: - * type: string - * X-Amz-Signature: - * type: string - * modelID: - * type: string - * format: uuid - * example: - * url: http://alfalfa.lan:9000/alfalfa - * fields: - * bucket: alfalfa - * X-Amz-Algorithm: AWS4-HMAC-SHA256 - * X-Amz-Credential: AKIA4MRT6LFGGPHNCKOO/20230309/us-west-1/s3/aws4_request - * X-Amz-Date: 20230309T200246Z - * key: uploads/5c1a0300-beb5-11ed-8531-d9fb035ab2f0/my_model.zip - * Policy: eyJleHBpcmF0aW9uIjoiMjAyMy0wMy0wOVQyMTowMjo0NloiLCJjb25kaXRpb25zIjpbeyJidWNrZXQiOiJhbGZhbGZhIn0seyJYLUFtei1BbGdvcml0aG0iOiJBV1M0LUhNQUMtU0hBMjU2In0seyJYLUFtei1DcmVkZW50aWFsIjoiQUtJQTRNUlQ2TEZHR1BITkNLT08vMjAyMzAzMDkvdXMtd2VzdC0xL3MzL2F3czRfcmVxdWVzdCJ9LHsiWC1BbXotRGF0ZSI6IjIwMjMwMzA5VDIwMDI0NloifSx7ImtleSI6InVwbG9hZHMvNWMxYTAzMDAtYmViNS0xMWVkLTg1MzEtZDlmYjAzNWFiMmYwL215X21vZGVsLnppcCJ9XX0= - * X-Amz-Signature: 7d09a673e65112ee06c7666c34eb9c4ca13cc43f285efc9c1c497befd3a64343 - * modelID: 5c1a0300-beb5-11ed-8531-d9fb035ab2f0 - */ router.post("/models/upload", async (req, res, next) => { const { modelName } = req.body; @@ -1138,35 +506,6 @@ router.get("/models/:modelId", (req, res) => { res.status(200).json({ payload: api.formatModel(req.model) }); }); -/** - * @openapi - * /models/{modelId}/createRun: - * post: - * operationId: Create run - * description: Create a run for a model - * tags: - * - Model - * parameters: - * - $ref: '#/components/parameters/ModelID' - * responses: - * 200: - * description: Create run response - * content: - * application/json: - * schema: - * type: object - * properties: - * runID: - * type: string - * example: - * runID: 28f76e90-bef6-11ed-822a-e3558db4daaf - * 404: - * description: Model ID does not exist - * content: - * application/json: - * schema: - * $ref: '#/components/schemas/Error' - */ router.post("/models/:modelId/createRun", (req, res, next) => { api .createRunFromModel(req.model) @@ -1185,48 +524,6 @@ router.get("/models/:modelId/download", (req, res, next) => { .catch(next); }); -/** - * @openapi - * /simulations: - * get: - * operationId: List simulations - * description: Return list of simulations - * tags: - * - Simulation - * responses: - * 200: - * description: Simulations response - * content: - * application/json: - * schema: - * type: object - * properties: - * data: - * type: array - * items: - * $ref: '#/components/schemas/Simulation' - * example: - * data: - * - id: cecbd6e0-c387-11ed-a3bc-35e2ce8e7182 - * name: Building 1 - * timeCompleted: 2022-03-15T12:00:00.000Z - * status: complete - * url: http://alfalfa.lan:9000/alfalfa/run/cecbd6e0-c387-11ed-a3bc-35e2ce8e7182.tar.gz?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=user%2F20230316%2Fus-west-1%2Fs3%2Faws4_request&X-Amz-Date=20220315T120000Z&X-Amz-Expires=86400&X-Amz-Signature=b46f963fcce33a29bbd2a8f93ea2b5368570acd20033bc5ce1372eeb59e08bfa&X-Amz-SignedHeaders=host&response-content-disposition=attachment%3B%20filename%3D%22Building%201.tar.gz%22&x-id=GetObject - * results: {} - * - id: 9bac1450-c396-11ed-92b6-db6f8d94933d - * name: Building 2 - * timeCompleted: 2022-03-16T12:00:00.000Z - * status: complete - * url: http://alfalfa.lan:9000/alfalfa/run/9bac1450-c396-11ed-92b6-db6f8d94933d.tar.gz?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=user%2F20230316%2Fus-west-1%2Fs3%2Faws4_request&X-Amz-Date=20220316T120000Z&X-Amz-Expires=86400&X-Amz-Signature=b46f963fcce33a29bbd2a8f93ea2b5368570acd20033bc5ce1372eeb59e08bfa&X-Amz-SignedHeaders=host&response-content-disposition=attachment%3B%20filename%3D%22Building%202.tar.gz%22&x-id=GetObject - * results: {} - */ -router.get("/simulations", async (req, res, next) => { - api - .listSimulations() - .then((payload) => res.json({ payload })) - .catch(next); -}); - router.all("*", (req, res) => res.status(404).json({ message: "Page not found" })); router.use(errorHandler);