From 9204695ed9f41d5229a9b6272e9386fc9202050a Mon Sep 17 00:00:00 2001 From: Christopher Atkins Date: Fri, 1 Nov 2024 17:58:50 +0000 Subject: [PATCH 01/13] using limit-type for slim media types --- .../schemas/array-max-monitored-elements.yaml | 2 +- .../_data/paths/limits_forecast-snapshot.yaml | 15 ++++++++++++-- .../_data/paths/limits_realtime-snapshot.yaml | 2 +- .../paths/rating-proposals_forecasts.yaml | 20 ++++++++++++++++++- .../paths/rating-proposals_realtime.yaml | 19 +++++++++++++++++- .../paths/rating-proposals_seasonal.yaml | 2 +- 6 files changed, 53 insertions(+), 7 deletions(-) diff --git a/docs/_data/components/schemas/array-max-monitored-elements.yaml b/docs/_data/components/schemas/array-max-monitored-elements.yaml index 9ce73299..bacd16b3 100644 --- a/docs/_data/components/schemas/array-max-monitored-elements.yaml +++ b/docs/_data/components/schemas/array-max-monitored-elements.yaml @@ -12,7 +12,7 @@ forecast-limits-snapshot: items: $ref: 'array-max-forecast-periods.yaml#/forecast-limit-item' -forecast-limits-slim-snapshot: +forecast-limits-snapshot-slim: type: object description: A snapshot of the forecast for a monitoring set. properties: diff --git a/docs/_data/paths/limits_forecast-snapshot.yaml b/docs/_data/paths/limits_forecast-snapshot.yaml index 382c38f9..65c767c3 100644 --- a/docs/_data/paths/limits_forecast-snapshot.yaml +++ b/docs/_data/paths/limits_forecast-snapshot.yaml @@ -23,6 +23,17 @@ current: requested, which also references the source proposals used to generate the snapshot, as well as reporting data from the ratings clearing process. + Additionally, the `application/vnd.trolie.forecast-limits-snapshot-slim.v1+json` + media type may be used to request a more concise representation of the data. + The media type parameter `limit-type` is required to specify the type of limit + being requested. For example, + ```http + GET /limits/forecast-snapshot HTTP/1.1 + Accept: application/vnd.trolie.forecast-limits-snapshot-slim.v1+json; limit-type=apparent-power + ``` + Note this format is much more concise but requires significant care in processing. + See [Using Slim Media Types](../example-narratives/using-slim-media-types) for more details. + Clients SHOULD perform Conditional `GET` using the `If-None-Match` header and the `ETag` of a previous `GET` response to poll this endpoint. Rate limiting is done on a per Ratings Provider basis, so requests from @@ -37,9 +48,9 @@ current: $ref: "../components/schemas/array-max-monitored-elements.yaml#/forecast-limits-snapshot" example: $ref: '../../example-narratives/examples/forecast-limits.json' - application/vnd.trolie.forecast-limits-slim-snapshot.v1+json: + application/vnd.trolie.forecast-limits-snapshot-slim.v1+json; limit-type=apparent-power: schema: - $ref: "../components/schemas/array-max-monitored-elements.yaml#/forecast-limits-slim-snapshot" + $ref: "../components/schemas/array-max-monitored-elements.yaml#/forecast-limits-snapshot-slim" example: $ref: '../../example-narratives/examples/forecast-limits-slim-active-power.json' application/vnd.trolie.forecast-limits-detailed-snapshot.v1+json: diff --git a/docs/_data/paths/limits_realtime-snapshot.yaml b/docs/_data/paths/limits_realtime-snapshot.yaml index cb80e8ec..b5d9e779 100644 --- a/docs/_data/paths/limits_realtime-snapshot.yaml +++ b/docs/_data/paths/limits_realtime-snapshot.yaml @@ -30,7 +30,7 @@ global: $ref: "../components/schemas/array-max-monitored-elements.yaml#/realtime-limits-detailed-snapshot" example: $ref: '../../example-narratives/examples/realtime-limit-set-detailed.json' - application/vnd.trolie.realtime-limits-snapshot-slim.v1+json: + application/vnd.trolie.realtime-limits-snapshot-slim.v1+json; limit-type=apparent-power: schema: $ref: "../components/schemas/array-max-monitored-elements.yaml#/realtime-limits-snapshot-slim" example: diff --git a/docs/_data/paths/rating-proposals_forecasts.yaml b/docs/_data/paths/rating-proposals_forecasts.yaml index dfde94ef..ed3bcbeb 100644 --- a/docs/_data/paths/rating-proposals_forecasts.yaml +++ b/docs/_data/paths/rating-proposals_forecasts.yaml @@ -75,6 +75,24 @@ patch: leveraged to split a large proposal into one or more parts in cases where that is advantageous from a performance or reliable delivery perspective. + + There are two supported media types for a Real-Time Ratings proposals. + + `application/vnd.trolie.rating-forecast-proposal.v1+json` allows the + Ratings Provider to combine different limit types, such as + `apparent-power` (MVA) and `current` (MW), in a single proposal. + + `application/vnd.trolie.rating-forecast-proposal-slim.v1+json` for + proposals that only require a single limit type, e.g., `apparent-power`. + Clients *MUST* specify that [limit-type](#tag/limit-type) as a media type + parameter. For example, + ```http + PATCH /ratings-proposals/forecast HTTP/1.1 + Content-Type: application/vnd.trolie.rating-forecast-proposal-slim.v1+json; limit-type=apparent-power + ``` + Note that this format is much more concise but requires significant care + in serialization/deserialization. For details, see [Using Slim Media Types](../example-narratives/using-slim-media-types). + requestBody: required: true content: @@ -83,7 +101,7 @@ patch: $ref: ../components/schemas/array-max-monitored-elements.yaml#/forecast-proposal example: $ref: ../../example-narratives/examples/forecast-ratings-proposal-patch.json - application/vnd.trolie.rating-forecast-proposal-slim.v1+json: + application/vnd.trolie.rating-forecast-proposal-slim.v1+json; limit-type=apparent-power: schema: $ref: ../components/schemas/array-max-monitored-elements.yaml#/forecast-proposal-slim example: diff --git a/docs/_data/paths/rating-proposals_realtime.yaml b/docs/_data/paths/rating-proposals_realtime.yaml index 07c017c2..a4937d77 100644 --- a/docs/_data/paths/rating-proposals_realtime.yaml +++ b/docs/_data/paths/rating-proposals_realtime.yaml @@ -82,6 +82,23 @@ post: data that is either completely missing, or is considered stale by the Clearinghouse Provider, likely due to simply not receiving a value within a reasonable period, such as an hour. + There are two supported media types for a Real-Time Ratings proposals. + + `application/vnd.trolie.rating-realtime-proposal.v1+json` allows the + Ratings Provider to combine different limit types, such as + `apparent-power` (MVA) and `current` (MW), in a single proposal. + + `application/vnd.trolie.rating-realtime-proposal-slim.v1+json` for + proposals that only require a single limit type, e.g., `apparent-power`. + Clients *MUST* specify that [limit-type](#tag/limit-type) as a media type + parameter. For example, + ```http + POST /ratings-proposals/realtime HTTP/1.1 + Content-Type: application/vnd.trolie.rating-realtime-proposal-slim.v1+json; limit-type=apparent-power + ``` + Note that this format is much more concise but requires significant care + in serialization/deserialization. For details, see [Using Slim Media Types](../example-narratives/using-slim-media-types). + tags: *tags requestBody: @@ -92,7 +109,7 @@ post: $ref: "../components/schemas/array-max-monitored-elements.yaml#/realtime-proposal" example: $ref: ../../example-narratives/examples/realtime-proposal.json - application/vnd.trolie.rating-realtime-proposal-slim.v1+json: + application/vnd.trolie.rating-realtime-proposal-slim.v1+json; limit-type=apparent-power: schema: $ref: "../components/schemas/array-max-monitored-elements.yaml#/realtime-proposal-slim" example: diff --git a/docs/_data/paths/rating-proposals_seasonal.yaml b/docs/_data/paths/rating-proposals_seasonal.yaml index c7570ca2..bb6a1689 100644 --- a/docs/_data/paths/rating-proposals_seasonal.yaml +++ b/docs/_data/paths/rating-proposals_seasonal.yaml @@ -104,7 +104,7 @@ patch: $ref: "../components/schemas/array-max-monitored-elements.yaml#/seasonal-ratings-proposal" example: $ref: ../../example-narratives/examples/seasonal-ratings-proposals-patch.json - application/vnd.trolie.seasonal-ratings-proposal-slim.v1+json: + application/vnd.trolie.seasonal-ratings-proposal-slim.v1+json; limit-type=apparent-power: schema: $ref: "../components/schemas/array-max-monitored-elements.yaml#/seasonal-ratings-proposal-slim" example: From 995401608cd48cb6e3b6ef712c3450d1e57e2d2b Mon Sep 17 00:00:00 2001 From: Christopher Atkins Date: Fri, 1 Nov 2024 19:32:37 +0000 Subject: [PATCH 02/13] add include-psr-header media type parameter --- .../schemas/array-max-monitored-elements.yaml | 29 ++++-- docs/_data/components/schemas/headers.yaml | 17 +++- .../_data/paths/limits_forecast-snapshot.yaml | 22 +++++ ...st-limits-detailed-elide-names-header.json | 99 +++++++++++++++++++ .../examples/forecast-limits-elide-psr.json | 62 ++++++++++++ 5 files changed, 219 insertions(+), 10 deletions(-) create mode 100644 docs/example-narratives/examples/forecast-limits-detailed-elide-names-header.json create mode 100644 docs/example-narratives/examples/forecast-limits-elide-psr.json diff --git a/docs/_data/components/schemas/array-max-monitored-elements.yaml b/docs/_data/components/schemas/array-max-monitored-elements.yaml index bacd16b3..2b93241c 100644 --- a/docs/_data/components/schemas/array-max-monitored-elements.yaml +++ b/docs/_data/components/schemas/array-max-monitored-elements.yaml @@ -1,4 +1,4 @@ -forecast-limits-snapshot: +forecast-limits-snapshot: &forecast-limit-snapshot type: object description: A snapshot of the forecast for a monitoring set. properties: @@ -11,9 +11,12 @@ forecast-limits-snapshot: description: Set of forecast limits items: $ref: 'array-max-forecast-periods.yaml#/forecast-limit-item' + required: + - snapshot-header + - limits forecast-limits-snapshot-slim: - type: object + <<: *forecast-limit-snapshot description: A snapshot of the forecast for a monitoring set. properties: snapshot-header: @@ -23,22 +26,36 @@ forecast-limits-snapshot-slim: items: $ref: 'array-max-forecast-periods.yaml#/resource-forecast-proposal-slim' -forecast-limits-detailed-snapshot: - type: object +forecast-limits-snapshot-elide-psr: + <<: *forecast-limit-snapshot + properties: + snapshot-header: + $ref: ./headers.yaml#/forecast-snapshot-header-elide-psr + limits: *max + +forecast-limits-detailed-snapshot-elide-psr: &forecast-limit-detailed + <<: *forecast-limit-snapshot description: | A detailed snapshot of the forecast for a monitoring set. These details are meant to support analysis, archival, and troubleshooting. - properties: + properties: &forecast-limit-detailed-props snapshot-header: - $ref: ./headers.yaml#/forecast-snapshot-header + $ref: ./headers.yaml#/forecast-snapshot-header-elide-psr limits: <<: *max description: Forecast including provenance information. items: $ref: 'array-max-forecast-periods.yaml#/forecast-limit-item-detailed' +forecast-limits-detailed-snapshot: + <<: *forecast-limit-detailed + properties: + <<: *forecast-limit-detailed-props + snapshot-header: + $ref: ./headers.yaml#/forecast-snapshot-header + named-power-system-resources: &psr <<: *max description: Collection of power system resource names diff --git a/docs/_data/components/schemas/headers.yaml b/docs/_data/components/schemas/headers.yaml index 6fd2e394..ce241eab 100644 --- a/docs/_data/components/schemas/headers.yaml +++ b/docs/_data/components/schemas/headers.yaml @@ -86,9 +86,9 @@ forecast-proposal-slim-header: - default-emergency-durations - power-system-resources -forecast-snapshot-header: &forecast-snapshot-header +forecast-snapshot-header-elide-psr: description: Details about the snapshot provided by the Clearinghouse provider. - properties: &forecast-snapshot-header-props + properties: &forecast-snapshot-header-elide-psr-props begins: <<: *begins description: | @@ -98,10 +98,19 @@ forecast-snapshot-header: &forecast-snapshot-header source: $ref: ./data-provenance.yaml - power-system-resources: - $ref: ./array-max-monitored-elements.yaml#/named-power-system-resources default-emergency-durations: $ref: ./array-max-emergency-durations.yaml#/emergency-durations + required: + - begins + - source + - default-emergency-durations + +forecast-snapshot-header: &forecast-snapshot-header + description: Details about the snapshot provided by the Clearinghouse provider. + properties: &forecast-snapshot-header-props + <<: *forecast-snapshot-header-elide-psr-props + power-system-resources: + $ref: ./array-max-monitored-elements.yaml#/named-power-system-resources required: - begins - source diff --git a/docs/_data/paths/limits_forecast-snapshot.yaml b/docs/_data/paths/limits_forecast-snapshot.yaml index 65c767c3..f1fc4918 100644 --- a/docs/_data/paths/limits_forecast-snapshot.yaml +++ b/docs/_data/paths/limits_forecast-snapshot.yaml @@ -23,6 +23,18 @@ current: requested, which also references the source proposals used to generate the snapshot, as well as reporting data from the ratings clearing process. + The `application/vnd.trolie.forecast-limits-snapshot.v1+json` and + `application/vnd.trolie.forecast-limits-detailed-snapshot.v1+json` media + types support the `include-psr-header` parameter. This is a boolean + parameter that defaults to `true`. When set to `false`, the + `power-system-resource` header is omitted. This can result in smaller + payloads when the client already knows the resource ids in use by the + Clearinghouse Provider. + ```http + GET /limits/forecast-snapshot HTTP/1.1 + Accept: application/vnd.trolie.forecast-limits-detailed-snapshot.v1+json; include-psr-header=false + ``` + Additionally, the `application/vnd.trolie.forecast-limits-snapshot-slim.v1+json` media type may be used to request a more concise representation of the data. The media type parameter `limit-type` is required to specify the type of limit @@ -44,6 +56,11 @@ current: description: The requested operating forecast snapshot is returned. content: application/vnd.trolie.forecast-limits-snapshot.v1+json: + schema: + $ref: "../components/schemas/array-max-monitored-elements.yaml#/forecast-limits-snapshot-elide-psr" + example: + $ref: '../../example-narratives/examples/forecast-limits-elide-psr.json' + application/vnd.trolie.forecast-limits-snapshot.v1+json; include-psr-header=false: schema: $ref: "../components/schemas/array-max-monitored-elements.yaml#/forecast-limits-snapshot" example: @@ -58,6 +75,11 @@ current: $ref: "../components/schemas/array-max-monitored-elements.yaml#/forecast-limits-detailed-snapshot" example: $ref: "../../example-narratives/examples/forecast-limits-detailed.json" + application/vnd.trolie.forecast-limits-detailed-snapshot.v1+json; include-psr-header=false: + schema: + $ref: "../components/schemas/array-max-monitored-elements.yaml#/forecast-limits-detailed-snapshot-elide-psr" + example: + $ref: "../../example-narratives/examples/forecast-limits-detailed-elide-names-header.json" headers: $ref: '../openapi-split.yaml#/components/responses/204/headers' '304': diff --git a/docs/example-narratives/examples/forecast-limits-detailed-elide-names-header.json b/docs/example-narratives/examples/forecast-limits-detailed-elide-names-header.json new file mode 100644 index 00000000..82141e73 --- /dev/null +++ b/docs/example-narratives/examples/forecast-limits-detailed-elide-names-header.json @@ -0,0 +1,99 @@ +{ + "snapshot-header": { + "begins": "2023-07-12T16:00:00-07:00", + "source": { + "provider":"X-AMPL-RC", + "last-updated": "2023-07-12T16:00:00-07:00", + "origin-id": "//trolie.example.com/snapshots/2024-08-05T11%3a00%3a00-07%3a00" + }, + "default-emergency-durations": [ + { + "name": "lte", + "duration-minutes": 240 + }, + { + "name": "ste", + "duration-minutes": 30 + }, + { + "name": "dal", + "duration-minutes": 15 + } + ] + }, + "limits": [ + { + "resource-id": "8badf00d", + "periods": [ + { + "period-start": "2023-07-12T16:00:00-07:00", + "period-end": "2023-07-12T17:00:00-07:00", + "proposals-considered": [ + { + "resource-id": "8badf00d-UTILITY-A-SEG-id", + "source": { + "last-updated": "2023-07-12T16:00:00-07:00", + "provider": "UTILITY-A", + "origin-id": "8badf00d-UTILITY-A-correlation-id" + }, + "period-start": "2023-07-12T16:00:00-07:00", + "period-end": "2023-07-12T17:00:00-07:00", + "proposal-disposition": "Used", + "continuous-operating-limit": { + "mva": 150 + }, + "emergency-operating-limits": [ + { + "duration-name": "lte", + "limit": { + "mva": 160 + } + }, + { + "duration-name": "ste", + "limit": { + "mva": 165 + } + }, + { + "duration-name": "dal", + "limit": { + "mva": 170 + } + } + ] + } + ], + "temporary-aar-exceptions": ["2d8c80e8-f533-4be9-85bf-f7f81eb73d67"], + "override-reason": "Any reason entered by the operator for an override.", + "additional-data": { + "vendor-specific-data": {} + }, + "continuous-operating-limit": { + "mva": 160 + }, + "emergency-operating-limits": [ + { + "duration-name": "lte", + "limit": { + "mva": 165 + } + }, + { + "duration-name": "ste", + "limit": { + "mva": 170 + } + }, + { + "duration-name": "dal", + "limit": { + "mva": 180 + } + } + ] + } + ] + } + ] +} diff --git a/docs/example-narratives/examples/forecast-limits-elide-psr.json b/docs/example-narratives/examples/forecast-limits-elide-psr.json new file mode 100644 index 00000000..3dedde94 --- /dev/null +++ b/docs/example-narratives/examples/forecast-limits-elide-psr.json @@ -0,0 +1,62 @@ +{ + "snapshot-header": { + "begins": "2023-07-12T16:00:00-07:00", + "source": { + "provider":"X-AMPL", + "last-updated": "2023-07-12T16:00:00-07:00", + "origin-id": "//trolie.example.com/snapshots/2024-08-05T11%3a00%3a00-07%3a00" + }, + "default-emergency-durations": [ + { + "name": "lte", + "duration-minutes": 240 + }, + { + "name": "ste", + "duration-minutes": 30 + }, + { + "name": "dal", + "duration-minutes": 15 + } + ] + }, + "limits": [ + { + "resource-id": "8badf00d", + "periods": [ + { + "period-start": "2023-07-12T16:00:00-07:00", + "period-end": "2023-07-12T17:00:00-07:00", + "continuous-operating-limit": { + "mw": 160, + "pf": 1.0 + }, + "emergency-operating-limits": [ + { + "duration-name": "lte", + "limit": { + "mw": 170, + "pf": 1.0 + } + }, + { + "duration-name": "ste", + "limit": { + "mw": 180, + "pf": 1.0 + } + }, + { + "duration-name": "dal", + "limit": { + "mw": 190, + "pf": 1.0 + } + } + ] + } + ] + } + ] +} \ No newline at end of file From 462b79cf8236038b11320046651516f8a05ca144 Mon Sep 17 00:00:00 2001 From: Christopher Atkins Date: Fri, 1 Nov 2024 20:01:37 +0000 Subject: [PATCH 03/13] the 1.9 version of webrick has some deps I'm dubious about --- docs/Gemfile | 2 +- docs/Gemfile.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/Gemfile b/docs/Gemfile index 56bef89f..8fbeb9b7 100644 --- a/docs/Gemfile +++ b/docs/Gemfile @@ -2,7 +2,7 @@ source ENV['GEM_REPO'] gem "github-pages", "~> 232", group: :jekyll_plugins -gem "webrick", "~> 1.8" +gem "webrick", "~> 1.8.2" gem "just-the-docs" diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock index 55657583..daca6ba0 100644 --- a/docs/Gemfile.lock +++ b/docs/Gemfile.lock @@ -279,7 +279,7 @@ DEPENDENCIES github-pages (~> 232) jekyll-redirect-from just-the-docs - webrick (~> 1.8) + webrick (~> 1.8.2) BUNDLED WITH 2.3.7 From c342b44d89228f0ddd8e4e9cf7da420b6cf57d4d Mon Sep 17 00:00:00 2001 From: Christopher Atkins Date: Fri, 1 Nov 2024 20:01:58 +0000 Subject: [PATCH 04/13] initial draft of slim usage examples --- docs/articles/media-types.md | 148 +------------- .../using-slim-media-types.md | 181 ++++++++++++++++++ 2 files changed, 183 insertions(+), 146 deletions(-) create mode 100644 docs/example-narratives/using-slim-media-types.md diff --git a/docs/articles/media-types.md b/docs/articles/media-types.md index b5ff324d..cd3074ad 100644 --- a/docs/articles/media-types.md +++ b/docs/articles/media-types.md @@ -114,12 +114,6 @@ details. #### Slim Media Types {: .no_toc } -{: .nb } -> At the time of this writing, -> `application/vnd.trolie.seasonal-ratings-proposal-slim.v1+json` is the only -> "slim" media type that has been implemented, but others are -> [planned](https://github.com/trolie/spec/issues/152). - The media types in the table above are verbose because they make intentional trade-offs between efficiency and other qualities. For more information please review the article [Performance Trade-offs in the TROLIE Schema Design](./tradeoffs). @@ -128,148 +122,10 @@ Because the TROLIE specification chose to [leverage media types to evolve the interface](../decision-log/media-type-versioning), the project was able to implement a "slim" media type use for seasonal ratings, `application/vnd.trolie.seasonal-ratings-proposal-slim.v1+json`, that -complements `application/vnd.trolie.seasonal-ratings-proposal.v1+json`. This -"slim" format is much more space-efficient but requires a few processing steps -and assumptions: - -1. The `limit-type` used in the proposal is specified by the Ratings Provider as -a parameter of the media type. The `limit-type` chosen determines the layout of -the ratings values. -2. The ratings are provided in order of decreasing duration, e.g., continuous -then emergency then load shed. -3. The facilities are required to be in the same order they appear in the -header. -4. The seasons are required to be in the same order they appear in the header. -5. Each forecast must have the number of hourly forecasts corresponding to the -new header field hours with the assumption that the begins header is the first -entry and each subsequent entry represents the subsequent hour's forecast. - -This is discussed in further detail in the -[spec](../spec#schema/seasonal-proposals-slim). Here we can breakdown a concrete -example. We'll start with a `curl` request, then discuss the HTTP request itself -in two parts, the headers then the JSON payload. - -##### `curl` Example -{: .no_toc } - -{% include_relative snippets/_accept-header-placeholder-warning.md %} -```sh -curl -X PATCH \ - -H "Content-Type: application/vnd.trolie.seasonal-ratings-proposal-slim.v1+json; limit-type=apparent-power" \ - -H "Accept: application/vnd.trolie.seasonal-ratings-proposal-status.v1+json, */*" \ - -d @seasonal-ratings.json \ - $TROLIE_SERVER_URL/ratings-proposals/seasonal -``` - -{: .important } -> The `limit-type` parameter in the `Content-Type` header (line 2 above) is -> required by the TROLIE specification for the -> `application/vnd.trolie.seasonal-ratings-proposal-slim.v1+json` media type, as -> no default `limit-type` can be assumed. See [Limit -> Types](../spec#tag/limit-type) for the other options defined in the spec. +complements `application/vnd.trolie.seasonal-ratings-proposal.v1+json`. {: .nb } -> The `Accept` header in this example specifies one of the -> [Status Responses](#status-responses). - -##### HTTP Headers -{: .no_toc } - -The previous `curl` request would result in an HTTP request like the following: - -```http -PATCH /ratings-proposals/seasonal HTTP/1.1 -Host: trolie.example.com -Accept: application/vnd.trolie.seasonal-ratings-proposal-status.v1+json, */* -Content-Type: application/vnd.trolie.seasonal-ratings-proposal-slim.v1+json; limit-type=apparent-power -``` - -##### Payload -{: .no_toc } - -{: .important } -> For illustrative purposes here, we present the JSON payload with inline -> comments. However, comments are **not** permitted in the TROLIE media types. - -```jsonc -{ - "proposal-header": { - "source": { /* ...details elided for clarity... */ }, - "default-emergency-durations": [ - { "name": "emergency", "duration-minutes": 240 }, - { "name": "load shed", "duration-minutes": 15 } - ], - "power-system-resources": [ - { "resource-id": "8badf00d", - "alternate-identifiers": [ { "name": "segmentX", "authority": "TO-NERC-ID" } ] - }, { - "resource-id": "f34d3d", - "alternate-identifiers": [ { "name": "segmentY", "authority": "TO-NERC-ID" } ] - } - ], - "default-seasonal-schedule": { - "schedule": [ - { "season-name": "WINTER", "begins": "2024-11-15T00:00:00-05:00" }, - { "season-name": "SPRING", "begins": "2025-03-01T00:00:00-05:00" }, - { "season-name": "SUMMER", "begins": "2025-06-15T00:00:00-05:00" }, - { "season-name": "FALL", "begins": "2025-09-01T00:00:00-05:00" } - ], - "ends": "2025-11-15T00:00:00-05:00" - } - }, - "ratings": [ - // note all values are assumed to be MVA because the header in this example - // Content-Type: application/vnd.trolie.seasonal-ratings-proposal-slim.v1+json; limit-type=apparent-power - // specifies the apparent-power limit type which has a single value of MVA - // see https://trolie.energy/spec#tag/limit-type - - [ // resource-id: 8badf00d - [ // season-name: WINTER - 160, //continuous MVA - 170, //emergency MVA - 200, //load shed MVA - ], - [ // season-name: SPRING - 155, //continuous MVA - 160, //emergency MVA - 200 //load shed MVA - ], - [ // season-name: SUMMER - 145, //continuous MVA - 150, //emergency MVA - 200 //load shed MVA - ], - [ // season-name: FALL - 155, //continuous MVA - 160, //emergency MVA - 200 //load shed MVA - ] - ], - [ // resource-id: f34d3d - [ // season-name: WINTER - 161, //continuous MVA - 171, //emergency MVA - 201 //load shed MVA - ], - [ // season-name: SPRING - 156, //continuous MVA - 161, //emergency MVA - 201 //load shed MVA - ], - [ // season-name: SUMMER - 146, //continuous MVA - 151, //emergency MVA - 201 //load shed MVA - ], - [ // season-name: FALL - 156, //continuous MVA - 161, //emergency MVA - 201 //load shed MVA - ] - ] - ] -} -``` +> For more information see [Using Slim Media Types](../example-narratives/using-slim-media-types) ### Status Responses diff --git a/docs/example-narratives/using-slim-media-types.md b/docs/example-narratives/using-slim-media-types.md new file mode 100644 index 00000000..9c26d8cb --- /dev/null +++ b/docs/example-narratives/using-slim-media-types.md @@ -0,0 +1,181 @@ +--- +title: Using Slim Media Types +parent: Usage Examples +nav_order: 8 +toc: true +--- + +The "slim" media types provided by TROLIE include: + +* `application/vnd.trolie.rating-realtime-proposal-slim.v1+json` +* `application/vnd.trolie.seasonal-ratings-proposal-slim.v1+json` +* `application/vnd.trolie.rating-forecast-proposal-slim.v1+json` +* `application/vnd.trolie.forecast-limits-snapshot-slim.v1+json` +* `application/vnd.trolie.realtime-limits-snapshot-slim.v1+json` + +These slim snapshots and proposals require the `limit-type` media type parameter +to be specified. The following names are valid values for the `limit-type` +parameter. + + * `active-power` + * `active-power-with-power-factor` + * `apparent-power` + * `current` + * `current-with-kV` + * `reactive-power` + * `overvoltage-threshold-pu` + * `overvoltage-threshold` + * `undervoltage-threshold-pu` + * `undervoltage-threshold` + +These correspond to the valid [Limit Types](../spec#tag/limit-type). + +Here's an example that requests a slim forecast limits snapshot +```http +GET /limits/forecast-snapshot HTTP/1.1 +Accept: application/vnd.trolie.forecast-limits-snapshot-slim.v1+json; limit-type=apparent-power +``` + + + + This +"slim" format is much more space-efficient but requires a few processing steps +and assumptions: + +1. The `limit-type` used in the proposal is specified by the Ratings Provider as +a parameter of the media type. The `limit-type` chosen determines the layout of +the ratings values. +2. The ratings are provided in order of decreasing duration, e.g., continuous +then emergency then load shed. +3. The facilities are required to be in the same order they appear in the +header. +4. The seasons are required to be in the same order they appear in the header. +5. Each forecast must have the number of hourly forecasts corresponding to the +new header field hours with the assumption that the begins header is the first +entry and each subsequent entry represents the subsequent hour's forecast. + +This is discussed in further detail in the +[spec](../spec#schema/seasonal-proposals-slim). Here we can breakdown a concrete +example. We'll start with a `curl` request, then discuss the HTTP request itself +in two parts, the headers then the JSON payload. + +##### `curl` Example +{: .no_toc } + +```sh +curl -X PATCH \ + -H "Content-Type: application/vnd.trolie.seasonal-ratings-proposal-slim.v1+json; limit-type=apparent-power" \ + -H "Accept: application/vnd.trolie.seasonal-ratings-proposal-status.v1+json, */*" \ + -d @seasonal-ratings.json \ + $TROLIE_SERVER_URL/ratings-proposals/seasonal +``` + +{: .important } +> The `limit-type` parameter in the `Content-Type` header (line 2 above) is +> required by the TROLIE specification for the +> `application/vnd.trolie.seasonal-ratings-proposal-slim.v1+json` media type, as +> no default `limit-type` can be assumed. See [Limit +> Types](../spec#tag/limit-type) for the other options defined in the spec. + +{: .nb } +> The `Accept` header in this example specifies one of the +> [Status Responses](#status-responses). + +##### HTTP Headers +{: .no_toc } + +The previous `curl` request would result in an HTTP request like the following: + +```http +PATCH /ratings-proposals/seasonal HTTP/1.1 +Host: trolie.example.com +Accept: application/vnd.trolie.seasonal-ratings-proposal-status.v1+json, */* +Content-Type: application/vnd.trolie.seasonal-ratings-proposal-slim.v1+json; limit-type=apparent-power +``` + +##### Payload +{: .no_toc } + +{: .important } +> For illustrative purposes here, we present the JSON payload with inline +> comments. However, comments are **not** permitted in the TROLIE media types. + +```jsonc +{ + "proposal-header": { + "source": { /* ...details elided for clarity... */ }, + "default-emergency-durations": [ + { "name": "emergency", "duration-minutes": 240 }, + { "name": "load shed", "duration-minutes": 15 } + ], + "power-system-resources": [ + { "resource-id": "8badf00d", + "alternate-identifiers": [ { "name": "segmentX", "authority": "TO-NERC-ID" } ] + }, { + "resource-id": "f34d3d", + "alternate-identifiers": [ { "name": "segmentY", "authority": "TO-NERC-ID" } ] + } + ], + "default-seasonal-schedule": { + "schedule": [ + { "season-name": "WINTER", "begins": "2024-11-15T00:00:00-05:00" }, + { "season-name": "SPRING", "begins": "2025-03-01T00:00:00-05:00" }, + { "season-name": "SUMMER", "begins": "2025-06-15T00:00:00-05:00" }, + { "season-name": "FALL", "begins": "2025-09-01T00:00:00-05:00" } + ], + "ends": "2025-11-15T00:00:00-05:00" + } + }, + "ratings": [ + // note all values are assumed to be MVA because the header in this example + // Content-Type: application/vnd.trolie.seasonal-ratings-proposal-slim.v1+json; limit-type=apparent-power + // specifies the apparent-power limit type which has a single value of MVA + // see https://trolie.energy/spec#tag/limit-type + + [ // resource-id: 8badf00d + [ // season-name: WINTER + 160, //continuous MVA + 170, //emergency MVA + 200, //load shed MVA + ], + [ // season-name: SPRING + 155, //continuous MVA + 160, //emergency MVA + 200 //load shed MVA + ], + [ // season-name: SUMMER + 145, //continuous MVA + 150, //emergency MVA + 200 //load shed MVA + ], + [ // season-name: FALL + 155, //continuous MVA + 160, //emergency MVA + 200 //load shed MVA + ] + ], + [ // resource-id: f34d3d + [ // season-name: WINTER + 161, //continuous MVA + 171, //emergency MVA + 201 //load shed MVA + ], + [ // season-name: SPRING + 156, //continuous MVA + 161, //emergency MVA + 201 //load shed MVA + ], + [ // season-name: SUMMER + 146, //continuous MVA + 151, //emergency MVA + 201 //load shed MVA + ], + [ // season-name: FALL + 156, //continuous MVA + 161, //emergency MVA + 201 //load shed MVA + ] + ] + ] +} +``` From ebb45dc5237d5d221d296c7a34d9cb5074891104 Mon Sep 17 00:00:00 2001 From: Christopher Atkins Date: Mon, 4 Nov 2024 13:38:35 +0000 Subject: [PATCH 05/13] improve descriptions --- docs/_data/components/schemas/headers.yaml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/_data/components/schemas/headers.yaml b/docs/_data/components/schemas/headers.yaml index 461437f4..7561e695 100644 --- a/docs/_data/components/schemas/headers.yaml +++ b/docs/_data/components/schemas/headers.yaml @@ -89,7 +89,9 @@ forecast-proposal-slim-header: - power-system-resources forecast-snapshot-header-elide-psr: - description: Details about the snapshot provided by the Clearinghouse provider. + description: | + Details about the snapshot provided by the Clearinghouse provider. The + `power-system-resources` property is omitted from this header. properties: &forecast-snapshot-header-elide-psr-props <<: *common-header-props begins: @@ -170,9 +172,8 @@ seasonal-proposal-header-slim: Defines the seasonal schedule that is used in the proposal. Each season is defined in the `schedule` array and the `ends` property defines the - end of the last season. - - Each individual facility proposal must have + end of the last season. Each individual facility proposal must have + corresponding entry for each entry In the `schedule` array. properties: schedule: From ba2abc7ad6f8bb1f8c7adc5b75cfa3f67c9fd167 Mon Sep 17 00:00:00 2001 From: Christopher Atkins Date: Mon, 4 Nov 2024 14:07:59 +0000 Subject: [PATCH 06/13] breadcrumb for where the limit-type names come from in the relevant media type parameter --- docs/_data/components/schemas/limit.yaml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/_data/components/schemas/limit.yaml b/docs/_data/components/schemas/limit.yaml index e0c8be5a..6f144afd 100644 --- a/docs/_data/components/schemas/limit.yaml +++ b/docs/_data/components/schemas/limit.yaml @@ -10,6 +10,21 @@ description: | `application/problem+json` response if they receive a proposal in an unsupported but valid limit type as defined here. + When used as the media type parameter `limit-type`, these are nominated by + the following names. + + * `active-power` + * `active-power-with-power-factor` + * `apparent-power` + * `current` + * `current-with-kV` + * `reactive-power` + * `overvoltage-threshold-pu` + * `overvoltage-threshold` + * `undervoltage-threshold-pu` + * `undervoltage-threshold` + + oneOf: - $ref: './limit-types/active-power.yaml' - $ref: './limit-types/active-power-with-power-factor.yaml' From eb82c0983fe607f15f5474362b6777c2e391f3d3 Mon Sep 17 00:00:00 2001 From: Christopher Atkins Date: Mon, 4 Nov 2024 15:02:32 +0000 Subject: [PATCH 07/13] add include-psr-header media type parameter --- .../schemas/array-max-monitored-elements.yaml | 56 +++--- docs/_data/components/schemas/headers.yaml | 28 +-- .../_data/paths/limits_realtime-snapshot.yaml | 10 + ...realtime-limit-set-detailed-elide-psr.json | 181 ++++++++++++++++++ .../realtime-limit-set-elide-psr.json | 51 +++++ 5 files changed, 292 insertions(+), 34 deletions(-) create mode 100644 docs/example-narratives/examples/realtime-limit-set-detailed-elide-psr.json create mode 100644 docs/example-narratives/examples/realtime-limit-set-elide-psr.json diff --git a/docs/_data/components/schemas/array-max-monitored-elements.yaml b/docs/_data/components/schemas/array-max-monitored-elements.yaml index f378fee5..047cb15b 100644 --- a/docs/_data/components/schemas/array-max-monitored-elements.yaml +++ b/docs/_data/components/schemas/array-max-monitored-elements.yaml @@ -67,9 +67,6 @@ forecast-limits-snapshot-slim: - name - values - unit - required: - - snapshot-header - - limits forecast-limits-snapshot-elide-psr: <<: *forecast-limit-snapshot @@ -265,10 +262,10 @@ real-time-proposal-status: - invalid-proposal-count - proposal-validation-errors -realtime-limits-snapshot: +realtime-limits-snapshot: &realtime-limit-snapshot type: object description: A snapshot of the realtime limits for a monitoring set. - properties: + properties: &realtime-limit-snapshot-props snapshot-header: $ref: ./headers.yaml#/real-time-snapshot-header limits: @@ -276,25 +273,15 @@ realtime-limits-snapshot: description: Real-time limits items: $ref: './realtime-limit-item.yaml#/normal' - -realtime-limits-detailed-snapshot: - type: object - description: A snapshot of the realtime limits for a monitoring set. - properties: - snapshot-header: - $ref: ./headers.yaml#/real-time-snapshot-header - limits: - <<: *max - description: Real-time limits including provenance. - items: - $ref: './realtime-limit-item.yaml#/detailed' + required: + - snapshot-header + - limits realtime-limits-snapshot-slim: - type: object + <<: *realtime-limit-snapshot description: A snapshot of the realtime limits for a monitoring set. properties: - snapshot-header: - $ref: ./headers.yaml#/real-time-snapshot-header + <<: *realtime-limit-snapshot-props limits: <<: *max description: Real-time limits @@ -320,9 +307,32 @@ realtime-limits-snapshot-slim: format: float nullable: true - required: - - snapshot-header - - limits +realtime-limits-snapshot-elide-psr: + <<: *realtime-limit-snapshot + properties: + <<: *realtime-limit-snapshot-props + snapshot-header: + $ref: ./headers.yaml#/real-time-snapshot-header-elide-psr + +realtime-limits-detailed-snapshot-elide-psr: + <<: *realtime-limit-snapshot + description: A snapshot of the realtime limits for a monitoring set. + properties: + snapshot-header: + $ref: ./headers.yaml#/real-time-snapshot-header-elide-psr + limits: + <<: *max + description: Real-time limits including provenance. + items: + $ref: './realtime-limit-item.yaml#/detailed' + +realtime-limits-detailed-snapshot: + <<: *realtime-limit-snapshot + description: A snapshot of the realtime limits for a monitoring set. + properties: + <<: *realtime-limit-snapshot-props + limits: + $ref: "#/realtime-limits-detailed-snapshot-elide-psr/properties/limits" realtime-proposal: type: object diff --git a/docs/_data/components/schemas/headers.yaml b/docs/_data/components/schemas/headers.yaml index 7561e695..9aeeaa5f 100644 --- a/docs/_data/components/schemas/headers.yaml +++ b/docs/_data/components/schemas/headers.yaml @@ -1,22 +1,24 @@ -common-header: &common-header +base-header: &base-header type: object - - properties: &common-header-props + properties: &base-header-props source: $ref: ./data-provenance.yaml - default-emergency-durations: $ref: ./array-max-emergency-durations.yaml#/emergency-durations - power-system-resources: - $ref: ./array-max-monitored-elements.yaml#/named-power-system-resources default-limiting-analysis: $ref: ./limiting-analysis.yaml + additionalProperties: false +common-header: &common-header + <<: *base-header + properties: &common-header-props + <<: *base-header-props + power-system-resources: + $ref: ./array-max-monitored-elements.yaml#/named-power-system-resources required: - source - default-emergency-durations - power-system-resources - additionalProperties: false real-time-proposal-header: &forecast-proposal-header <<: *common-header @@ -93,7 +95,7 @@ forecast-snapshot-header-elide-psr: Details about the snapshot provided by the Clearinghouse provider. The `power-system-resources` property is omitted from this header. properties: &forecast-snapshot-header-elide-psr-props - <<: *common-header-props + <<: *base-header-props begins: <<: *begins description: | @@ -141,13 +143,17 @@ forecast-snapshot-slim-header: - power-system-resources - default-emergency-durations -real-time-snapshot-header: +real-time-snapshot-header-elide-psr: description: Details about the snapshot provided by the Clearinghouse provider. properties: - <<: *common-header-props + <<: *base-header-props required: - source - - power-system-resources + - default-emergency-durations + +real-time-snapshot-header: + <<: *common-header + description: Details about the snapshot provided by the Clearinghouse provider. seasonal-proposal-header: <<: *common-header diff --git a/docs/_data/paths/limits_realtime-snapshot.yaml b/docs/_data/paths/limits_realtime-snapshot.yaml index b5d9e779..e9e50ea8 100644 --- a/docs/_data/paths/limits_realtime-snapshot.yaml +++ b/docs/_data/paths/limits_realtime-snapshot.yaml @@ -25,11 +25,21 @@ global: $ref: "../components/schemas/array-max-monitored-elements.yaml#/realtime-limits-snapshot" example: $ref: '../../example-narratives/examples/realtime-limit-set.json' + application/vnd.trolie.realtime-limits-snapshot.v1+json; include-psr-header=false: + schema: + $ref: "../components/schemas/array-max-monitored-elements.yaml#/realtime-limits-snapshot-elide-psr" + example: + $ref: '../../example-narratives/examples/realtime-limit-set-elide-psr.json' application/vnd.trolie.realtime-limits-detailed-snapshot.v1+json: schema: $ref: "../components/schemas/array-max-monitored-elements.yaml#/realtime-limits-detailed-snapshot" example: $ref: '../../example-narratives/examples/realtime-limit-set-detailed.json' + application/vnd.trolie.realtime-limits-detailed-snapshot.v1+json; include-psr-header=false: + schema: + $ref: "../components/schemas/array-max-monitored-elements.yaml#/realtime-limits-detailed-snapshot-elide-psr" + example: + $ref: '../../example-narratives/examples/realtime-limit-set-detailed-elide-psr.json' application/vnd.trolie.realtime-limits-snapshot-slim.v1+json; limit-type=apparent-power: schema: $ref: "../components/schemas/array-max-monitored-elements.yaml#/realtime-limits-snapshot-slim" diff --git a/docs/example-narratives/examples/realtime-limit-set-detailed-elide-psr.json b/docs/example-narratives/examples/realtime-limit-set-detailed-elide-psr.json new file mode 100644 index 00000000..e1edbc99 --- /dev/null +++ b/docs/example-narratives/examples/realtime-limit-set-detailed-elide-psr.json @@ -0,0 +1,181 @@ +{ + "snapshot-header": { + "source": { + "provider": "X-AMPL-RC", + "last-updated": "2023-07-12T15:05:43.044267100-07:00", + "origin-id": "//trolie.example.com/snapshots/2024-08-05T11%3a00%3a00-07%3a00" + }, + "default-emergency-durations": [ + { + "name": "lte", + "duration-minutes": 240 + }, + { + "name": "ste", + "duration-minutes": 30 + }, + { + "name": "dal", + "duration-minutes": 5 + } + ] + }, + "limits": [ + { + "resource-id": "8badf00d", + "period-start": "2025-07-12T15:00:00-07:00", + "period-end": "2025-07-12T16:00:00-07:00", + "proposals-considered": [ + { + "resource-id": "8badf00d-UTILITY-A-SEG-id", + "source": { + "last-updated": "2025-07-12T14:10:12-07:00", + "provider": "UTILITY-A", + "origin-id": "8badf00d-UTILITY-A-correlation-id" + }, + "period-start": "2025-07-12T15:00:00-07:00", + "period-end": "2025-07-12T16:00:00-07:00", + "proposal-disposition": "Used", + "continuous-operating-limit": { + "mva": 150 + }, + "emergency-operating-limits": [ + { + "duration-name": "lte", + "limit": { + "mva": 165 + } + }, + { + "duration-name": "ste", + "limit": { + "mva": 170 + } + }, + { + "duration-name": "dal", + "limit": { + "mva": 180 + } + } + ] + }, + { + "resource-id": "8badf00d-UTILITY-B-SEG-id", + "source": { + "last-updated": "2025-07-12T14:10:12-07:00", + "provider": "UTILITY-B", + "origin-id": "8badf00d-UTILITY-B-correlation-id" + }, + "period-start": "2025-07-12T15:00:00-07:00", + "period-end": "2025-07-12T16:00:00-07:00", + "proposal-disposition": "Used", + "continuous-operating-limit": { + "mva": 150 + }, + "emergency-operating-limits": [ + { + "duration-name": "lte", + "limit": { + "mva": 166 + } + }, + { + "duration-name": "ste", + "limit": { + "mva": 171 + } + }, + { + "duration-name": "dal", + "limit": { + "mva": 175 + } + } + ] + } + ], + "temporary-aar-exceptions": [ + { + "id": "284928-2025-07-12T16:00:00-07:00", + "source": { + "origin-id": "2d8c80e8-f533-4be9-85bf-f7f81eb73d67", + "provider": "UTILITY-A", + "last-updated": "2025-07-12T16:00:00-07:00" + }, + "resource": { + "resource-id": "8badf00d" + }, + "start-time": "2025-07-12T16:00:00-07:00", + "end-time": "2025-08-01T00:00:00-07:00", + "continuous-operating-limit": { + "mva": 160 + }, + "emergency-operating-limits": [ + { + "duration-name": "lte", + "limit": { + "mva": 165 + } + }, + { + "duration-name": "ste", + "limit": { + "mva": 170 + } + }, + { + "duration-name": "dal", + "limit": { + "mva": 180 + } + } + ] + } + ], + "overrides": [ + { + "continuous-operating-limit": { + "mva": 160 + }, + "emergency-operating-limits": [ + { + "duration-name": "lte", + "limit": { + "mva": 165 + } + } + ], + "override-reason": "TOI 20250701-01", + "start-time": "2025-07-01T00:00:00-07:00" + } + ], + "additional-data": { + "vendor-specific-data": {} + }, + "continuous-operating-limit": { + "mva": 160 + }, + "emergency-operating-limits": [ + { + "duration-name": "lte", + "limit": { + "mva": 165 + } + }, + { + "duration-name": "ste", + "limit": { + "mva": 170 + } + }, + { + "duration-name": "dal", + "limit": { + "mva": 175 + } + } + ] + } + ] +} \ No newline at end of file diff --git a/docs/example-narratives/examples/realtime-limit-set-elide-psr.json b/docs/example-narratives/examples/realtime-limit-set-elide-psr.json new file mode 100644 index 00000000..79e7b760 --- /dev/null +++ b/docs/example-narratives/examples/realtime-limit-set-elide-psr.json @@ -0,0 +1,51 @@ +{ + "snapshot-header": { + "source": { + "provider":"X-AMPL", + "last-updated": "2023-07-12T15:05:43.044267100-07:00", + "origin-id": "//trolie.example.com/snapshots/2024-08-05T11%3a00%3a00-07%3a00" + }, + "default-emergency-durations": [ + { + "name": "lte", + "duration-minutes": 240 + }, + { + "name": "ste", + "duration-minutes": 30 + }, + { + "name": "dal", + "duration-minutes": 15 + } + ] + }, + "limits": [ + { + "resource-id": "8badf00d", + "continuous-operating-limit": { + "mva": 160 + }, + "emergency-operating-limits": [ + { + "duration-name": "lte", + "limit": { + "mva": 165 + } + }, + { + "duration-name": "ste", + "limit": { + "mva": 170 + } + }, + { + "duration-name": "dal", + "limit": { + "mva": 180 + } + } + ] + } + ] +} \ No newline at end of file From 00412149de7635e1ff098f88199c4ceef364b65c Mon Sep 17 00:00:00 2001 From: Christopher Atkins Date: Mon, 4 Nov 2024 16:05:30 +0000 Subject: [PATCH 08/13] add include-psr-header media type parameter to seasonal snapshot --- .../schemas/array-max-monitored-elements.yaml | 21 ++++- docs/_data/components/schemas/headers.yaml | 9 +- .../paths/seasonal-ratings-snapshot.yaml | 5 + ...l-ratings-snapshot-detailed-elide-psr.json | 94 +++++++++++++++++++ 4 files changed, 121 insertions(+), 8 deletions(-) create mode 100644 docs/example-narratives/examples/seasonal-ratings-snapshot-detailed-elide-psr.json diff --git a/docs/_data/components/schemas/array-max-monitored-elements.yaml b/docs/_data/components/schemas/array-max-monitored-elements.yaml index 047cb15b..c16daa76 100644 --- a/docs/_data/components/schemas/array-max-monitored-elements.yaml +++ b/docs/_data/components/schemas/array-max-monitored-elements.yaml @@ -459,26 +459,41 @@ seasonal-ratings-proposal-status: - incomplete-obligation-count - invalid-proposal-count -seasonal-ratings-snapshot: +seasonal-ratings-snapshot: &seasonal-rating-snapshot type: object description: A snapshot of the seasonal ratings for a monitoring set. - properties: &seasonal-rating-snapshot-props + properties: snapshot-header: $ref: ./headers.yaml#/common-header ratings: <<: *max items: $ref: ./array-max-seasons.yaml#/seasonal-rating-snapshot-item + required: + - snapshot-header + - ratings + seasonal-ratings-snapshot-detailed: + <<: *seasonal-rating-snapshot description: A snapshot of the seasonal ratings for a monitoring set. properties: - <<: *seasonal-rating-snapshot-props + snapshot-header: + $ref: ./headers.yaml#/common-header ratings: <<: *max items: $ref: ./array-max-seasons.yaml#/seasonal-rating-snapshot-item-detailed +seasonal-ratings-snapshot-detailed-elide-psr: + <<: *seasonal-rating-snapshot + description: A snapshot of the seasonal ratings for a monitoring set. + properties: + snapshot-header: + $ref: ./headers.yaml#/base-header + ratings: + $ref: "#/seasonal-ratings-snapshot-detailed/properties/ratings" + temporary-aar-exception-set: type: array minItems: 0 diff --git a/docs/_data/components/schemas/headers.yaml b/docs/_data/components/schemas/headers.yaml index 9aeeaa5f..193722d9 100644 --- a/docs/_data/components/schemas/headers.yaml +++ b/docs/_data/components/schemas/headers.yaml @@ -8,6 +8,9 @@ base-header: &base-header default-limiting-analysis: $ref: ./limiting-analysis.yaml additionalProperties: false + required: + - source + - default-emergency-durations common-header: &common-header <<: *base-header @@ -144,12 +147,8 @@ forecast-snapshot-slim-header: - default-emergency-durations real-time-snapshot-header-elide-psr: + <<: *base-header description: Details about the snapshot provided by the Clearinghouse provider. - properties: - <<: *base-header-props - required: - - source - - default-emergency-durations real-time-snapshot-header: <<: *common-header diff --git a/docs/_data/paths/seasonal-ratings-snapshot.yaml b/docs/_data/paths/seasonal-ratings-snapshot.yaml index 5078aa3c..edefbe6d 100644 --- a/docs/_data/paths/seasonal-ratings-snapshot.yaml +++ b/docs/_data/paths/seasonal-ratings-snapshot.yaml @@ -21,6 +21,11 @@ get: $ref: ../components/schemas/array-max-monitored-elements.yaml#/seasonal-ratings-snapshot-detailed example: $ref: '../../example-narratives/examples/seasonal-ratings-snapshot-detailed.json' + application/vnd.trolie.seasonal-rating-snapshot-detailed.v1+json; include-psr-header=false: + schema: + $ref: ../components/schemas/array-max-monitored-elements.yaml#/seasonal-ratings-snapshot-detailed-elide-psr + example: + $ref: '../../example-narratives/examples/seasonal-ratings-snapshot-detailed-elide-psr.json' headers: $ref: '../openapi-split.yaml#/components/responses/204/headers' diff --git a/docs/example-narratives/examples/seasonal-ratings-snapshot-detailed-elide-psr.json b/docs/example-narratives/examples/seasonal-ratings-snapshot-detailed-elide-psr.json new file mode 100644 index 00000000..0719ce06 --- /dev/null +++ b/docs/example-narratives/examples/seasonal-ratings-snapshot-detailed-elide-psr.json @@ -0,0 +1,94 @@ +{ + "snapshot-header": { + "source": { + "provider": "X-AMPL", + "last-updated": "2023-07-12T16:00:00-07:00", + "origin-id": "//trolie.example.com/snapshots/2024-08-05T11%3a00%3a00-07%3a00" + }, + "default-emergency-durations": [ + { + "name": "lte", + "duration-minutes": 240 + }, + { + "name": "ste", + "duration-minutes": 30 + }, + { + "name": "dal", + "duration-minutes": 15 + } + ] + }, + "ratings": [ + { + "resource-id": "LINE1", + "periods": [ + { + "period-start": "2024-04-01T01:00:00Z", + "period-end": "2024-07-01T01:00:00Z", + "season-name": "spring", + "continuous-operating-limit": { + "mva": 160 + }, + "emergency-operating-limits": [ + { + "duration-name": "lte", + "limit": { + "mva": 165 + } + }, + { + "duration-name": "ste", + "limit": { + "mva": 170 + } + }, + { + "duration-name": "dal", + "limit": { + "mva": 180 + } + } + ], + "proposals-considered": [ + { + "resource-id": "8badf00d", + "period-start": "2024-04-01T01:00:00Z", + "period-end": "2024-07-01T01:00:00Z", + "source": { + "provider": "X-AMPL", + "last-updated": "2023-07-12T16:00:00-07:00", + "origin-id": "//trolie.example.com/snapshots/2024-08-05T11%3a00%3a00-07%3a00" + }, + "season-name": "spring", + "continuous-operating-limit": { + "mva": 160 + }, + "emergency-operating-limits": [ + { + "duration-name": "lte", + "limit": { + "mva": 165 + } + }, + { + "duration-name": "ste", + "limit": { + "mva": 170 + } + }, + { + "duration-name": "dal", + "limit": { + "mva": 180 + } + } + ] + } + ] + } + ] + } + ] +} From d0e28005e1f8f569e91c184e526386e81e8f7def Mon Sep 17 00:00:00 2001 From: Christopher Atkins Date: Mon, 4 Nov 2024 21:12:29 +0000 Subject: [PATCH 09/13] and input-used examples --- .../paths/rating-proposals_forecasts.yaml | 11 +++- .../paths/rating-proposals_realtime.yaml | 7 ++- ...-ratings-proposal-slim-patch-dry-bulb.json | 55 +++++++++++++++++++ .../forecast-ratings-proposal-slim-patch.json | 12 +--- ...realtime-proposal-slim-patch-dry-bulb.json | 41 ++++++++++++++ 5 files changed, 111 insertions(+), 15 deletions(-) create mode 100644 docs/example-narratives/examples/forecast-ratings-proposal-slim-patch-dry-bulb.json create mode 100644 docs/example-narratives/examples/realtime-proposal-slim-patch-dry-bulb.json diff --git a/docs/_data/paths/rating-proposals_forecasts.yaml b/docs/_data/paths/rating-proposals_forecasts.yaml index ed3bcbeb..7bdde2a7 100644 --- a/docs/_data/paths/rating-proposals_forecasts.yaml +++ b/docs/_data/paths/rating-proposals_forecasts.yaml @@ -104,8 +104,15 @@ patch: application/vnd.trolie.rating-forecast-proposal-slim.v1+json; limit-type=apparent-power: schema: $ref: ../components/schemas/array-max-monitored-elements.yaml#/forecast-proposal-slim - example: - $ref: ../../example-narratives/examples/forecast-ratings-proposal-slim-patch.json + examples: + "No Inputs Provided": + summary: No Inputs Provided in the Forecast Proposal + value: + $ref: ../../example-narratives/examples/forecast-ratings-proposal-slim-patch.json + "Dry Bulb Temp Provided": + summary: Dry Bulb Temp Provided in the Forecast Proposal + value: + $ref: ../../example-narratives/examples/forecast-ratings-proposal-slim-patch-dry-bulb.json responses: '202': diff --git a/docs/_data/paths/rating-proposals_realtime.yaml b/docs/_data/paths/rating-proposals_realtime.yaml index a4937d77..4724a9e8 100644 --- a/docs/_data/paths/rating-proposals_realtime.yaml +++ b/docs/_data/paths/rating-proposals_realtime.yaml @@ -112,8 +112,11 @@ post: application/vnd.trolie.rating-realtime-proposal-slim.v1+json; limit-type=apparent-power: schema: $ref: "../components/schemas/array-max-monitored-elements.yaml#/realtime-proposal-slim" - example: - $ref: ../../example-narratives/examples/realtime-proposal-slim-patch.json + examples: + "No Inputs Provided": + summary: No Inputs Provided in the Real-Time Proposal + value: + $ref: ../../example-narratives/examples/realtime-proposal-slim-patch.json responses: '202': description: | diff --git a/docs/example-narratives/examples/forecast-ratings-proposal-slim-patch-dry-bulb.json b/docs/example-narratives/examples/forecast-ratings-proposal-slim-patch-dry-bulb.json new file mode 100644 index 00000000..c8404971 --- /dev/null +++ b/docs/example-narratives/examples/forecast-ratings-proposal-slim-patch-dry-bulb.json @@ -0,0 +1,55 @@ +{ + "proposal-header" : { + "source": { + "last-updated": "2025-10-31T15:05:43.044267100-07:00", + "provider": "UTILITY-A", + "origin-id": "5aeacb25-9b65-4738-8a00-ac10afa63640" + }, + "begins": "2025-11-01T01:00:00-05:00", + "ends": "2025-11-01T05:00:00-05:00", + "default-emergency-durations": [ + { + "name": "emergency", + "duration-minutes": 240 + } + ], + "power-system-resources": [ + { "resource-id": "8badf00d", + "alternate-identifiers": [ + {"name": "segmentX", "authority": "TO-NERC-ID"}, + {"name": "LINE1 SEG-X", "authority": "RC-NERC-ID", "mrid": "8badf00d"} + ] + }, + { "resource-id": "f34d3d", + "alternate-identifiers": [ + {"name": "segmentY", "authority": "TO-NERC-ID"}, + {"name": "LINE2 SEG-Y", "authority": "RC-NERC-ID", "mrid": "8badf00d"} + ] + } + ] + }, + "ratings": [ + [ + [160, 170], + [155, 160], + [145, 150], + [140, 145] + ], + [ + [160, 170], + [155, 160], + [145, 150], + [140, 145] + ] + ], + "inputs-used": [ + { + "name": "dry bulb temperature (Fahrenheit)", + "unit": "degF", + "values": [ + [ 50, 51, 52, 53 ], + [ 46.1, 46.5, 47.1, 48 ] + ] + } + ] +} diff --git a/docs/example-narratives/examples/forecast-ratings-proposal-slim-patch.json b/docs/example-narratives/examples/forecast-ratings-proposal-slim-patch.json index 08815db2..305adeb5 100644 --- a/docs/example-narratives/examples/forecast-ratings-proposal-slim-patch.json +++ b/docs/example-narratives/examples/forecast-ratings-proposal-slim-patch.json @@ -41,15 +41,5 @@ [145, 150], [140, 145] ] - ], - "inputs-used": [ - { - "name": "dry bulb temperature (Fahrenheit)", - "unit": "degF", - "values": [ - [ 50, 51, 52, 53 ], - [ 46.1, 46.5, 47.1, 48 ] - ] - } ] -} \ No newline at end of file +} diff --git a/docs/example-narratives/examples/realtime-proposal-slim-patch-dry-bulb.json b/docs/example-narratives/examples/realtime-proposal-slim-patch-dry-bulb.json new file mode 100644 index 00000000..3e8cde88 --- /dev/null +++ b/docs/example-narratives/examples/realtime-proposal-slim-patch-dry-bulb.json @@ -0,0 +1,41 @@ +{ + "proposal-header" : { + "source": { + "last-updated": "2025-10-31T15:05:43.044267100-07:00", + "provider": "UTILITY-A", + "origin-id": "5aeacb25-9b65-4738-8a00-ac10afa63640" + }, + "default-emergency-durations": [ + { + "name": "emergency", + "duration-minutes": 240 + } + ], + "power-system-resources": [ + { "resource-id": "8badf00d", + "alternate-identifiers": [ + {"name": "segmentX", "authority": "TO-NERC-ID"}, + {"name": "LINE1 SEG-X", "authority": "RC-NERC-ID", "mrid": "8badf00d"} + ] + }, + { "resource-id": "f34d3d", + "alternate-identifiers": [ + {"name": "segmentY", "authority": "TO-NERC-ID"}, + {"name": "LINE2 SEG-Y", "authority": "RC-NERC-ID", "mrid": "8badf00d"} + ] + } + ] + }, + "ratings": [ + [160, 170], + [155, 160] + ], + "inputs-used": [ + { + "name": "dry bulb temperature (Fahrenheit)", + "unit": "degF", + "values": [ + [ 50, 51] + ] + } + ]} From e372fbd68d255a0823a896139b905de9681143d3 Mon Sep 17 00:00:00 2001 From: Christopher Atkins Date: Tue, 5 Nov 2024 00:57:09 +0000 Subject: [PATCH 10/13] add inputs-used media type param to forecast snapshot --- .../_data/paths/limits_forecast-snapshot.yaml | 5 ++ ...ast-limits-slim-active-power-dry-bulb.json | 59 +++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 docs/example-narratives/examples/forecast-limits-slim-active-power-dry-bulb.json diff --git a/docs/_data/paths/limits_forecast-snapshot.yaml b/docs/_data/paths/limits_forecast-snapshot.yaml index f1fc4918..d581c11f 100644 --- a/docs/_data/paths/limits_forecast-snapshot.yaml +++ b/docs/_data/paths/limits_forecast-snapshot.yaml @@ -70,6 +70,11 @@ current: $ref: "../components/schemas/array-max-monitored-elements.yaml#/forecast-limits-snapshot-slim" example: $ref: '../../example-narratives/examples/forecast-limits-slim-active-power.json' + application/vnd.trolie.forecast-limits-snapshot-slim.v1+json; limit-type=apparent-power, inputs-used=true: + schema: + $ref: "../components/schemas/array-max-monitored-elements.yaml#/forecast-limits-snapshot-slim" + example: + $ref: '../../example-narratives/examples/forecast-limits-slim-active-power-dry-bulb.json' application/vnd.trolie.forecast-limits-detailed-snapshot.v1+json: schema: $ref: "../components/schemas/array-max-monitored-elements.yaml#/forecast-limits-detailed-snapshot" diff --git a/docs/example-narratives/examples/forecast-limits-slim-active-power-dry-bulb.json b/docs/example-narratives/examples/forecast-limits-slim-active-power-dry-bulb.json new file mode 100644 index 00000000..e305b9ce --- /dev/null +++ b/docs/example-narratives/examples/forecast-limits-slim-active-power-dry-bulb.json @@ -0,0 +1,59 @@ +{ + "snapshot-header": { + "begins": "2023-07-12T16:00:00-07:00", + "ends": "2023-07-12T18:00:00-07:00", + "source": { + "provider":"X-AMPL", + "last-updated": "2023-07-12T16:00:00-07:00", + "origin-id": "//trolie.example.com/snapshots/2024-08-05T11%3a00%3a00-07%3a00" + }, + "default-emergency-durations": [ + { + "name": "lte", + "duration-minutes": 240 + }, + { + "name": "ste", + "duration-minutes": 30 + }, + { + "name": "dal", + "duration-minutes": 15 + } + ], + "power-system-resources": [ + { "resource-id": "8badf00d", + "alternate-identifiers": [ + {"name": "segmentX", "authority": "TO-NERC-ID"}, + {"name": "LINE1 SEG-X", "authority": "RC-NERC-ID", "mrid": "8badf00d"} + ] + }, + { "resource-id": "f34d3d", + "alternate-identifiers": [ + {"name": "segmentY", "authority": "TO-NERC-ID"}, + {"name": "LINE2 SEG-Y", "authority": "RC-NERC-ID", "mrid": "8badf00d"} + ] + } + ] + }, + "limits": [ + [ + [160, 1.0, 170, 1.0, 180, 1.0, 190, 1.0], + [161, 1.0, 171, 1.0, 181, 1.0, 191, 1.0] + ], + [ + [140, 1.0, 150, 1.0, 160, 1.0, 170, 1.0], + [141, 1.0, 151, 1.0, 161, 1.0, 171, 1.0] + ] + ], + "inputs-used": [ + { + "name": "dry bulb temperature (Fahrenheit)", + "unit": "degF", + "values": [ + [ 50, 51, 52, 53 ], + [ 46.1, 46.5, 47.1, 48 ] + ] + } + ] +} \ No newline at end of file From f8069eaf6a3b70288f2edcc07f423ce05be5eb17 Mon Sep 17 00:00:00 2001 From: Christopher Atkins Date: Tue, 5 Nov 2024 01:21:27 +0000 Subject: [PATCH 11/13] add inputs-used media type param for RT limits snapshot --- .../schemas/array-max-monitored-elements.yaml | 16 +++++++- .../_data/paths/limits_realtime-snapshot.yaml | 5 +++ .../realtime-limit-set-slim-dry-bulb.json | 40 +++++++++++++++++++ 3 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 docs/example-narratives/examples/realtime-limit-set-slim-dry-bulb.json diff --git a/docs/_data/components/schemas/array-max-monitored-elements.yaml b/docs/_data/components/schemas/array-max-monitored-elements.yaml index c16daa76..bbba9cef 100644 --- a/docs/_data/components/schemas/array-max-monitored-elements.yaml +++ b/docs/_data/components/schemas/array-max-monitored-elements.yaml @@ -279,14 +279,22 @@ realtime-limits-snapshot: &realtime-limit-snapshot realtime-limits-snapshot-slim: <<: *realtime-limit-snapshot - description: A snapshot of the realtime limits for a monitoring set. - properties: + description: A slim snapshot of the realtime limits for a monitoring set. + properties: &realtime-limit-snapshot-slim-props <<: *realtime-limit-snapshot-props limits: <<: *max description: Real-time limits items: $ref: 'array-max-emergency-ratings.yaml#/slim' + +realtime-limits-snapshot-slim-inputs-used: + <<: *realtime-limit-snapshot + description: | + A slim snapshot of the realtime limits for a monitoring set, including the + inputs used to determine the limits. + properties: + <<: *realtime-limit-snapshot-slim-props inputs-used: <<: *inputs-used-slim items: @@ -306,6 +314,10 @@ realtime-limits-snapshot-slim: type: number format: float nullable: true + required: + - snapshot-header + - limits + - inputs-used realtime-limits-snapshot-elide-psr: <<: *realtime-limit-snapshot diff --git a/docs/_data/paths/limits_realtime-snapshot.yaml b/docs/_data/paths/limits_realtime-snapshot.yaml index e9e50ea8..12cfc8a1 100644 --- a/docs/_data/paths/limits_realtime-snapshot.yaml +++ b/docs/_data/paths/limits_realtime-snapshot.yaml @@ -45,6 +45,11 @@ global: $ref: "../components/schemas/array-max-monitored-elements.yaml#/realtime-limits-snapshot-slim" example: $ref: '../../example-narratives/examples/realtime-limit-set-slim.json' + application/vnd.trolie.realtime-limits-snapshot-slim.v1+json; limit-type=apparent-power; inputs-used=true: + schema: + $ref: "../components/schemas/array-max-monitored-elements.yaml#/realtime-limits-snapshot-slim-inputs-used" + example: + $ref: '../../example-narratives/examples/realtime-limit-set-slim-dry-bulb.json' headers: $ref: '../openapi-split.yaml#/components/responses/204/headers' '304': diff --git a/docs/example-narratives/examples/realtime-limit-set-slim-dry-bulb.json b/docs/example-narratives/examples/realtime-limit-set-slim-dry-bulb.json new file mode 100644 index 00000000..50f71f93 --- /dev/null +++ b/docs/example-narratives/examples/realtime-limit-set-slim-dry-bulb.json @@ -0,0 +1,40 @@ +{ + "snapshot-header": { + "source": { + "provider": "X-AMPL", + "last-updated": "2023-07-12T15:05:43.044267100-07:00", + "origin-id": "//trolie.example.com/snapshots/2024-08-05T11%3a00%3a00-07%3a00" + }, + "default-emergency-durations": [ + { + "name": "emergency", + "duration-minutes": 240 + } + ], + "power-system-resources": [ + { "resource-id": "8badf00d", + "alternate-identifiers": [ + { "name": "segmentX", "authority": "TO-NERC-ID" }, + { "name": "LINE1 SEG-X", "authority": "RC-NERC-ID", "mrid": "8badf00d" } + ] + }, + { "resource-id": "f34d3d", + "alternate-identifiers": [ + { "name": "segmentY", "authority": "TO-NERC-ID" }, + { "name": "LINE2 SEG-Y", "authority": "RC-NERC-ID", "mrid": "8badf00d" } + ] + } + ] + }, + "limits": [ + [ 160, 170 ], + [ 155, 160 ] + ], + "inputs-used": [ + { + "name": "dry bulb temperature (Fahrenheit)", + "unit": "degF", + "values": [ 50, 51] + } + ] +} From a87e173ac92204005bbad4aa065fe2124208b967 Mon Sep 17 00:00:00 2001 From: Christopher Atkins Date: Tue, 5 Nov 2024 01:27:17 +0000 Subject: [PATCH 12/13] refactor schema to require inputs-used when requested --- .../schemas/array-max-monitored-elements.yaml | 13 ++++++++++--- docs/_data/paths/limits_forecast-snapshot.yaml | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/docs/_data/components/schemas/array-max-monitored-elements.yaml b/docs/_data/components/schemas/array-max-monitored-elements.yaml index bbba9cef..8fca3ee7 100644 --- a/docs/_data/components/schemas/array-max-monitored-elements.yaml +++ b/docs/_data/components/schemas/array-max-monitored-elements.yaml @@ -17,14 +17,21 @@ forecast-limits-snapshot: &forecast-limit-snapshot forecast-limits-snapshot-slim: <<: *forecast-limit-snapshot - description: A snapshot of the forecast for a monitoring set. - properties: + description: A slim snapshot of the forecast for a monitoring set. + properties: &forecast-limit-snapshot-slim-props snapshot-header: $ref: ./headers.yaml#/forecast-snapshot-slim-header limits: <<: *max items: $ref: 'array-max-forecast-periods.yaml#/resource-forecast-proposal-slim' +forecast-limits-snapshot-slim-inputs-used: + <<: *forecast-limit-snapshot + description: | + A slim snapshot of the forecast for a monitoring set, including the inputs + that were used to determine the continuous limits. + properties: + <<: *forecast-limit-snapshot-slim-props inputs-used: &inputs-used-slim description: | @@ -292,7 +299,7 @@ realtime-limits-snapshot-slim-inputs-used: <<: *realtime-limit-snapshot description: | A slim snapshot of the realtime limits for a monitoring set, including the - inputs used to determine the limits. + inputs used to determine the continuous limits. properties: <<: *realtime-limit-snapshot-slim-props inputs-used: diff --git a/docs/_data/paths/limits_forecast-snapshot.yaml b/docs/_data/paths/limits_forecast-snapshot.yaml index d581c11f..61e73235 100644 --- a/docs/_data/paths/limits_forecast-snapshot.yaml +++ b/docs/_data/paths/limits_forecast-snapshot.yaml @@ -72,7 +72,7 @@ current: $ref: '../../example-narratives/examples/forecast-limits-slim-active-power.json' application/vnd.trolie.forecast-limits-snapshot-slim.v1+json; limit-type=apparent-power, inputs-used=true: schema: - $ref: "../components/schemas/array-max-monitored-elements.yaml#/forecast-limits-snapshot-slim" + $ref: "../components/schemas/array-max-monitored-elements.yaml#/forecast-limits-snapshot-slim-inputs-used" example: $ref: '../../example-narratives/examples/forecast-limits-slim-active-power-dry-bulb.json' application/vnd.trolie.forecast-limits-detailed-snapshot.v1+json: From b149986e5b7338fab75aa1f1045dd7e007bba7e5 Mon Sep 17 00:00:00 2001 From: Christopher Atkins Date: Tue, 5 Nov 2024 01:35:53 +0000 Subject: [PATCH 13/13] sync lock file --- docs/Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock index 948235bd..50c4bbd0 100644 --- a/docs/Gemfile.lock +++ b/docs/Gemfile.lock @@ -281,7 +281,7 @@ DEPENDENCIES github-pages (~> 232) jekyll-redirect-from just-the-docs - webrick (~> 1.8.2) + webrick (~> 1.8) BUNDLED WITH 2.3.7