siteapps / knmi-edr
PHP 8.4 client for the KNMI Environmental Data Retrieval API.
Requires
- php: ^8.4
- ext-curl: *
- ext-json: *
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-11-04 13:11:20 UTC
README
Composer-library in namespace KMNI\EDR, exact volgens de opgegeven spelling.
Package: kmni/edr. De SDK is niet gepubliceerd op Packagist.
Dezelfde opzet als de eerdere OpenHoliday SDK: Client, Configuration, een vervangbaar cURL-transport, getypeerde modellen, enums, aparte *Response-methodes, voorbeelden, dependencyvrije tests en GitHub Actions. Alleen PHP ^8.4, ext-curl en ext-json zijn nodig; geen Guzzle of andere runtimepackages.
Validatiestatus: de volledige KNMI OpenAPI-download werd in de maakomgeving door het netwerk geblokkeerd. De handgeschreven methodes zijn gebaseerd op de officiële KNMI EDR-documentatie en de EDR-responsstructuren. Er is geen volledige, automatisch gegenereerde één-op-één mapping van alle OpenAPI-schema’s en de endpointdekking is niet volledig geverifieerd. Er waren ook geen PHP/Composer-binaries beschikbaar om de meegeleverde tests te draaien. Zie VALIDATION.md. Met composer openapi:fetch kun je de actuele specificatie ophalen; callOperation() biedt aanvullende GET-toegang via de echte operationIds, met generieke JSON-responses.
Installeren
Pak dit project uit en voer in de projectmap uit:
composer installs iteapps/knmi-edr
Je kunt de SDK ook in een eigen Git-repository zetten en die als Composer vcs-repository opnemen. Er is bewust geen composer.lock of vendor in deze library-zip opgenomen.
Beginnen
Vraag een EDR API-key aan via de KNMI API-catalogus. Een Open Data API-key is een andere sleutel. De SDK verstuurt de EDR-key rechtstreeks in Authorization, zonder Bearer.
<?php require 'vendor/autoload.php'; use KMNI\EDR\Client; use KMNI\EDR\Configuration; $key = getenv('KNMI_EDR_API_KEY'); if ($key === false || $key === '') { throw new RuntimeException('KNMI_EDR_API_KEY ontbreekt.'); } $client = new Client(new Configuration(apiKey: $key)); foreach ($client->getCollections()->collections as $collection) { echo $collection->id, ': ', $collection->title, PHP_EOL; }
Stations en meetwaarden
Collecties bepalen welke parameters, querytypes, tijdvakken en formaten beschikbaar zijn. Vraag de metadata op voordat je parametercodes kiest. Namen uit oude KNMI-collecties zijn niet automatisch bruikbaar in nieuwe collecties.
use KMNI\EDR\Query\DataQuery; $id = '10-minute-in-situ-meteorological-observations'; $metadata = $client->getCollection($id); $stations = $client->getLocations($id); $stationId = (string) $stations->features[0]->id; $parameterName = array_key_first($metadata->parameterNames); $data = $client->getLocation( collectionId: $id, locationIds: $stationId, query: new DataQuery( datetime: '2025-07-19T06:00:00Z/2025-07-19T07:00:00Z', parameterNames: [(string) $parameterName], ), ); echo $data->toJson(JSON_PRETTY_PRINT);
Dit voorbeeld veronderstelt dat de metadata stations en parameters bevat. examples/station.php controleert lege resultaten. Controleer of het gekozen tijdvak binnen de actuele collectie-extent valt. Een lege query-uitkomst kan geldig zijn.
Meerdere stations: geef locationIds: ['0-20000-0-06260', '0-20000-0-06310'] op. Deze IDs zijn voorbeelden; de actuele lijst komt uit getLocations().
Gebiedsquery’s en instances
use KMNI\EDR\Query\DataQuery; use KMNI\EDR\Value\BoundingBox; use KMNI\EDR\Value\Wkt; $time = new DataQuery(datetime: '2025-07-19T12:00:00Z'); if ($metadata->supports('cube')) { $area = $client->getCube($id, new BoundingBox([3.0, 51.0, 4.5, 52.0]), $time); } if ($metadata->supports('position')) { $point = $client->getPosition($id, Wkt::point(3.61, 51.5), $time); }
Wkt::point() gebruikt x, y, bij de standaard geografische CRS dus lengtegraad, breedtegraad. Wkt::multiPoint() en Wkt::polygon() zijn beschikbaar. Voor andere WKT-vormen kun je rechtstreeks een WKT-string meegeven. WKT wordt niet volledig lokaal geparsed; de server valideert geometrie en collectie-specifieke eisen.
Wanneer de collectie instances aanbiedt, gebruik getInstances(), getInstance() en bij een dataquery de optionele named argument instanceId:. De SDK construeert dan /collections/{collectionId}/instances/{instanceId}/…. Niet iedere collectie biedt instances of ieder querytype aan; er vindt geen automatische capability-request plaats.
QueryType bevat daarnaast Radius, Trajectory en Corridor voor query()/queryResponse(). Dit zijn EDR-patronen, geen bewering dat KNMI ze voor een bepaalde collectie aanbiedt. Gebruik ze uitsluitend als de actuele metadata/spec ze vermeldt, met de daar voorgeschreven parameters.
Datum, hoogte en extra filters
DataQuery accepteert een datum, RFC 3339-tijdstip met tijdzone, DateTimeInterface of een gesloten/open interval. new DateTimeRange(null, '2025-01-01') levert ../2025-01-01. Twee open grenzen en omgekeerde intervallen worden geweigerd. Duration-gebaseerde intervallen worden niet door de typed helper ondersteund; gebruik zo nodig de generieke requestmethode.
$query = new DataQuery( datetime: '2025-07-19T06:00:00Z/2025-07-19T07:00:00Z', parameterNames: ['een-code-uit-de-metadata'], z: '0', crs: null, extra: ['een-filter-uit-de-specificatie' => 'waarde'], );
parameterNames wordt parameter-name met kommagescheiden codes. extra biedt toegang tot collectie-specifieke filters. De SDK verzint geen filtercodes en valideert niet de volledige OpenAPI-queryschema’s. Standaardparameters mogen niet dubbel worden opgegeven. Gebruik crs en z alleen indien ondersteund.
CoverageJSON verwerken
Een dataquery geeft een Coverage of CoverageCollection terug. De oorspronkelijke structuur, onbekende uitbreidingen en lege JSON-objecten blijven via toJson() bewaard. toArray() is een associatieve convenience-view; daarin worden lege objecten lege arrays. Zeer grote JSON-integers worden als strings ingelezen.
use KMNI\EDR\Model\CoverageCollection; $coverages = $data instanceof CoverageCollection ? $data->coverages : [$data]; foreach ($coverages as $coverage) { foreach ($coverage->ranges as $name => $range) { if (is_string($range)) { continue; // Externe range-URL, wordt niet automatisch gevolgd. } print_r($range->axisNames); print_r($range->shape); print_r($range->values); } }
NdArray::valueAt(['t' => 0, 'y' => 0, 'x' => 0]) indexeert op asnaam volgens de werkelijke axisNames-volgorde. Geef precies de aanwezige assen op; sommige responses hebben andere assen. null blijft een ontbrekende meetwaarde en wordt niet nul. Parameters kunnen op het CoverageCollection-niveau staan; ze worden niet impliciet in elk kind gekopieerd. De typed range-reader ondersteunt inline NdArray en range-URLs. Voor andere encodings, zoals getegelde ranges, gebruik je de ruwe response.
Ruwe responses en andere formaten
Iedere getypeerde endpointmethode heeft een *Response()-variant met HttpResponse: statusCode, headers, body, getHeader() en getHeaderLine(). Kies een outputformaat dat de collectie daadwerkelijk aanbiedt via DataQuery(format: ...). Typed dataquery-methodes verwachten CoverageJSON; gebruik voor andere formaten de responsevariant.
$response = $client->getCubeResponse($id, new BoundingBox([3.0, 51.0, 4.5, 52.0]), $time); file_put_contents('metingen.json', $response->body); echo $response->getHeaderLine('X-KNMI-Deprecation');
Voor aanvullende routes zijn request('/relatief/pad', $query) en requestResponse(...) beschikbaar. Alleen paden binnen de ingestelde API-root worden geaccepteerd. Queryarrays worden kommagescheiden geserialiseerd; herhaalde querysleutels en complexe OpenAPI deepObject-serialisatie zijn niet geïmplementeerd.
Actuele OpenAPI-specificatie
composer openapi:fetch php examples/openapi.php
openapi:fetch haalt de werkelijke specificatie op, valideert OpenAPI 3.x en schrijft openapi/openapi.json plus een SHA-256-bronmanifest. Dit gebeurt alleen als je het commando uitvoert. Het genereert geen extra PHP-klassen.
use KMNI\EDR\OpenApi\Document; $document = Document::fromJson(file_get_contents('openapi/openapi.json')); foreach ($document->getOperations() as $operation) { echo $operation->id, ' ', $operation->method, ' ', $operation->path, PHP_EOL; } // Vul bestaande operationId en exacte parameternamen uit de specificatie in: // $result = $client->callOperation($document, $operationId, $pathParameters, $queryParameters); // $raw = $client->callOperationResponse($document, $operationId, $pathParameters, $queryParameters);
De operation-router ondersteunt GET, interne $ref-verwijzingen, vereiste queryparameters en encoded padparameters. Hij voert geen volledige schema- of responsevalidatie uit, ondersteunt geen POST/body-operaties en volgt geen externe $ref-URLs. Responses zijn JsonDocument of HttpResponse, geen automatisch gegenereerde responseklasse per operationId. Operaties zonder operationId kun je via het relatieve pad aanroepen. Een opgegeven servers-URL wordt niet automatisch gevolgd; Configuration::baseUri bepaalt altijd de bestemming.
Fouten en transport
ApiException: HTTP buiten 200–299, met volledige response,getDetails(),getStatusCode()engetRetryAfterSeconds().TransportException: cURL-/verbindingsfout of timeout.DecodingException: ongeldige JSON of een niet-passende getypeerde respons, met response indien beschikbaar.InvalidArgumentException: ongeldige lokale invoer.
De SDK volgt geen redirects en doet geen automatische retries. Plan retries zelf, met name bij 429, rekening houdend met Retry-After. TLS-verificatie staat aan. Responses worden volledig in geheugen gelezen; vraag grote datasets in beperkte tijd-/gebiedsblokken op. Configuration biedt timeout, connectTimeout, baseUri, userAgent en aanvullende headers. De API-key staat niet in URLs en wordt gemaskeerd in debug-output van Configuration.
TransportInterface::get(string $url, array $headers): HttpResponse is injecteerbaar via new Client($configuration, $transport). Dit is dezelfde transportopzet als de OpenHoliday SDK. Alternatieve transports moeten alle HTTP-statuscodes teruggeven en alleen transportproblemen als TransportException melden.
Tests en voorbeelden
composer check # PHP-lint, unit tests, echte cURL-tests tegen localhost composer test:integration # 3 live metadata/schema-requests; slaat over zonder API-key php examples/basic.php php examples/station.php php examples/spatial.php php examples/openapi.php php examples/errors.php
De 16 unit-testgroepen gebruiken synthetische fixtures. Die zijn geen opgeslagen KNMI-responses. De transporttest start een lokale PHP-webserver en test headers, URL-parameters, redirects, foutstatussen en timeouts. GitHub Actions bevat PHP 8.4 en 8.5. Live tests draaien niet automatisch in CI en testen geen volledige dataquerymatrix.
Bronnen
- KNMI EDR-documentatie
- KNMI authenticatie en foutmeldingen
- KNMI OpenAPI
- KNMI nieuwe 10-minutencollectie
De bron-URL en de beperkingen van deze oplevering staan ook in openapi/source.json. Dit is een onafhankelijke SDK, geen officieel KNMI-package.