--- title: "EDR compatibility and supported scope" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{EDR compatibility and supported scope} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- `edr4r` targets the JSON ecosystem around OGC API - Environmental Data Retrieval. The EDR standard permits more encodings and deployment patterns than this package promises to parse. This article makes that boundary explicit so that a server advertising an EDR conformance class is not mistaken for a guarantee that every `edr4r` workflow will work unchanged. ## Client support | Capability | Status in edr4r | Notes | |---|---|---| | Landing page, conformance, collections, parameters, queryables | Supported | JSON discovery documents | | Collection instances | Supported | Discovery and instance-scoped query paths | | `locations`, `items`, `position`, `area`, `cube`, `radius`, `trajectory`, `corridor` | Supported | Read-only HTTP GET helpers; the server may implement only a subset | | EDR 1.0/1.1 conformance identifiers | Supported | Version-tolerant capability matching; current verified endpoints advertise 1.0 identifiers | | EDR 1.1 multi-geometries and custom dimensions | Supported subset | WKT `MULTIPOINT`, `MULTIPOLYGON`, and `MULTILINESTRING`; custom extent metadata is retained and named dimension parameters pass through `...` | | CoverageJSON | Supported subset | Inline `Coverage`/`CoverageCollection` with primitive, regular, or tuple axes and inline `NdArray` ranges; nonstandard coordinates are retained as `.axis_*` columns | | GeoJSON | Supported | Converted to `sf` when installed; otherwise retained as an `edr_response` | | CSV | Limited | Parsed by the low-level client and supported directly by location queries | | NetCDF, GeoTIFF, GRIB and other native encodings | Download only | Use `edr_request(..., parse = FALSE)` with the server's advertised `f` value; no native R conversion yet | | External CoverageJSON domains/ranges and `TiledNdArray` | Not supported | Rejected explicitly rather than partially or silently parsed | | Pagination/link following | Supported subset | Opt-in for GeoJSON FeatureCollections from `edr_locations()` / `edr_items()`; bounded by finite page and feature caps | | Multi-location retrieval | Supported subset | Explicit IDs through sequential `edr_location_batch()`; optional bounded calendar windows, custom-axis-aware exact deduplication, checkpoint/resume, CoverageJSON/CSV, and a finite expanded-plan cap | | HTTP 202/308 asynchronous polling | Not yet supported | HTTP 204 empty responses are supported | | POST queries and EDR Part 2 Pub/Sub | Out of current scope | The package is a synchronous, read-only client | CRS values are passed to the server as requested. `edr4r` retains effective CoverageJSON referencing metadata and does not silently reproject coverage coordinates. A projected grid remains valid in `edr_plot()`, which uses source coordinates. `edr_map()` requires WGS 84/CRS84 longitude/latitude: it rejects a declared projected or other known geographic CRS and out-of-range coordinates or inferred cell bounds. Missing or custom references produce a warning only after those range checks pass. Station `sf` geometry is transformed to WGS 84 for Leaflet display after any ID or source-CRS spatial matching has been completed; missing `sf` CRS metadata warns before plausible degree-range coordinates are used as-is. Current pygeoapi endpoints commonly serve GeoJSON and CoverageJSON through `f=json`, which remains the compatibility default. When a stricter endpoint advertises an encoding-specific token, pass it explicitly while keeping the desired parser, for example `edr_position(..., format = "covjson", f = "CoverageJSON")` or `edr_request(..., query = list(f = "CoverageJSON"), format = "covjson")`. ## Return and failure contract Discovery tables (`edr_collections()`, `edr_parameters()`, and `edr_instances()`) return tibbles with stable scalar columns and list columns for metadata that cannot be flattened without loss. Raw collection/instance documents remain available in a `raw` list column. Detailed discovery calls return the parsed JSON list. CoverageJSON query verbs return an `edr_response`; convert it explicitly with `covjson_to_tibble()`. GeoJSON collection verbs return `sf` when `sf` is installed and otherwise retain an `edr_response`. CSV responses return a tibble. HTTP 204 produces a typed empty result rather than a parser failure. The first nine CoverageJSON columns remain `coverage_id`, `parameter`, `parameter_label`, `unit`, `datetime`, `x`, `y`, `z`, and `value`. Nonstandard coordinates follow as `.axis_` columns without changing row cardinality. A versioned `edr_covjson_metadata` attribute retains per-coverage domain type, axis details, and effective referencing, including collection-level values inherited by child coverages. Package batch, explore, and checkpoint paths preserve that attribute; arbitrary third-party row binds are not promised to do so. For numeric CoverageJSON ranges, values serialized as JSON strings are coerced only when every non-missing string is finite and safely representable; actual text, overflow/underflow, and unsafe declared integers remain explicit parser errors. `edr_location_batch()` returns an `edr_location_batch` object with three stable tibbles: `requests` (one status row per planned location/window query), `data` (row-bound CoverageJSON/CSV data with `.request_id` and `.location_id` provenance), and `errors` (preserved conditions when `on_error = "collect"`). With explicit `include_parameters = TRUE`, a fourth `parameters` tibble holds the nonduplicated collection or instance parameter catalog; otherwise that component is `NULL` and no metadata request is made. Optional day/week/month/year chunks require a finite closed interval. Adjacent windows share their boundary; exact rows repeated across windows for the same location are removed by default, while `requests$n_rows` retains raw response counts. Timestamp bounds are normalized to UTC before calendar arithmetic and may contain up to six fractional-second digits; values that R cannot represent without loss are rejected before requests begin. It is sequential in this release so the normal client retry policy remains authoritative. Checkpointing is opt-in and preserves only terminal successful or empty parsed responses. An interrupted or failed request has no terminal file and is retried on the next explicit `resume = TRUE` call. Each checkpoint is locked while in use and fingerprinted against the effective endpoint, ordered location/window plan, format, and query arguments. A mismatch or corrupt result aborts before network activity. Headers, full query URLs, and error conditions are not stored; the parsed observation data is stored and should be protected accordingly. Checkpointed clients require an absolute HTTP(S) base URL without an embedded query, fragment, username, or password. Rotating credentials belong in client headers; the caller remains responsible for resuming under the same logical authorization context. The checkpoint schema is versioned with parser semantics. Schema 2 records the custom-axis identity and CoverageJSON metadata contract; earlier checkpoints are rejected explicitly and must be recreated rather than combined with newly parsed rows. Parameter catalogs are not checkpointed or included in the request-plan fingerprint. A resumed batch with `include_parameters = TRUE` obtains current metadata through the client's discovery cache even when every data request is restored. `max_requests` counts data requests only, and `on_error` does not collect a parameter-discovery failure. Pagination is deliberately opt-in. The client follows only the server-advertised body link with `rel = "next"`, treats its cursor/offset as opaque, and requires the continuation to remain on the original request's service origin. Reaching `max_pages` or `max_features` while another page exists is a typed error, not a silently partial result. `edr_explore()` does not enable collection-wide pagination automatically. Local argument and parser failures are raised before issuing unsafe follow-up requests. HTTP failures retain their `httr2_http_*` status classes and include a useful server error body when one is available. `edr_diagnose()` is the exception: after validating its arguments, it records metadata/network failures as `fail`, `warn`, or `skip` rows so one broken discovery endpoint does not hide the rest of the report. ## Inspect before querying The 0.2 discovery layer retains query-specific formats, units, CRS details, extents, and parameter metadata instead of flattening them away. ```r client <- edr_client("https://labs.metoffice.gov.uk/edr") service <- edr_capabilities(client) terrain <- edr_capabilities(client, "terrain_tiles") edr_supports(client, "terrain_tiles", query = "position") edr_supports( client, "terrain_tiles", query = "position", format = "CoverageJSON" ) # Fresh, metadata-only probes; no data query is issued. edr_diagnose(client, "terrain_tiles") ``` Discovery responses are cached per client for a bounded period. Use `refresh = TRUE` on a discovery call when current server state matters, or clear that client's metadata with `edr_cache_clear(client)`. ## Verified endpoints The table records direct compatibility checks, not a permanent availability promise. Server metadata and pagination behavior were last inspected on 2026-07-10. | Endpoint | Role | Advertised query types observed | edr4r coverage | |---|---|---|---| | [USGS waterdata](https://api.waterdata.usgs.gov/ogcapi/beta/) | Operational U.S. streamgage service | `locations` | Collection/location discovery, opaque cursor pagination, latest-record station/batch time series, CoverageJSON parsing, per-location exploration; location queries currently ignore `datetime` | | [Western Water Datahub](https://api.wwdh.internetofwater.app) | Operational multi-network pygeoapi deployment | `locations`, `items`, `position`, `area`, `cube` | Discovery, parameters, offset pagination for items, station and bulk queries, plotting and mapping | | [Met Office Labs](https://labs.metoffice.gov.uk/edr/collections?f=html) | Non-operational technical demonstrator | `locations`, `items`, `instances`, `position`, `area`, `cube`, `radius`, `trajectory` | Cross-implementation metadata, instances, query-specific formats, terrain point coverage, and an explicit-CRS population grid | The Met Office service describes itself as an example rather than an operational API. It is useful for interoperability testing because its metadata exercises instances and richer query variables, but production workflows must not depend on its availability. ## Frozen and live checks Tests use small, reviewed fixtures so CRAN and pull-request checks are deterministic and offline. Met Office fixtures retain the response shapes needed for capability, instance, and single-Coverage parsing tests while omitting large payloads and verbose WKT definitions. CoverageJSON axis bounds are not yet used as cell edges. Grid visualization infers cell bounds from coordinate centers, including range validation of the derived edges; external domains/ranges and tiled arrays remain unsupported as listed above. Frozen cursor- and offset-shaped pages exercise both pagination styles without relying on live service state. Security and edge-case tests also cover relative links, cycles, malformed/multiple next links, cross-origin continuations, and page or feature caps. A separate scheduled/manual workflow performs tiny, non-blocking live probes: bounded USGS cursor pagination and station batching, bounded WWDH offset pagination, plus the Met Office capability, terrain, and population-grid checks. An endpoint outage does not fail package CI; it is evidence of availability or interoperability drift to investigate. ## What "supports EDR" means here `edr4r` can construct every EDR Part 1 query path listed above, but a particular server may not advertise or implement each path or encoding. Use capability discovery rather than treating the existence of an R function as a server guarantee. For an unfamiliar endpoint, start with `edr_diagnose()`, inspect collection capabilities, and then issue the smallest representative query.