-
Notifications
You must be signed in to change notification settings - Fork 18
SOS SPS REST
SOS needs to expose the following resources:
- Service Capabilities (service info, offerings?)
- Procedures/Offerings
- Procedure Descriptions (history)
- Features of Interest (GeoJSON w/ CRS)
- Observations
- Data Streams
In addition, SPS needs to expose:
- Tasks and their status
- Control Streams
The following URL hierarchy can be used to access SOS resources in a REST fashion:
Root is http://domain/endpoint/v2
URL | Resource Type | Filtering | |
---|---|---|---|
/ | Service Info | ||
/procedures | Procedure[] | uid, text, geo, creation time, data time, obsprop, procgroup | |
/procedures/{id} | Procedure | ||
/descriptionHistory (desc) | AbstractProcess[] as SML-JSON | time | |
/descriptionHistory/latest | AbstractProcess as SML-JSON | ||
/descriptionHistory/{idx*} | AbstractProcess as SML-JSON | ||
/featuresOfInterest (fois) | Feature[] as GeoJSON | geo, data time, obsprop | |
/featuresOfInterest/latest | Feature[] as GeoJSON | geo, obsprop | |
/featuresOfInterest/{id} | Feature as GeoJSON | ||
/observations (obs) | Observation[] as OM-JSON | time, foi, obsprop, geo | |
/observations/{id} | Observation as OM-JSON | ||
/observations/latest | Observation as OM-JSON | ||
/dataStreams (streams) | DataStream[] as SWE-JSON | ||
/dataStreams/{id**} | DataStream as SWE-JSON | ||
/dataStreams/{id}/past | SWE Record[] (csv, json or binary) | time, foi, obsprop, geo | |
/dataStreams/{id}/latest | SWE Record (csv, json or binary) | foi, obsprop, geo | |
/dataStreams/{id}/live | SWE Record[] (csv, json or binary) | foi, obsprop, geo | |
For Tasking | |||
/taskingInputs | DataStream[] as SWE-JSON | ||
/taskingInputs/{id} | DataStream as SWE-JSON | ||
/taskingInputs/{id}/live | POST SWE Record as json | ||
/tasks | Task[] | time | |
/tasks/{id} | Task | ||
/tasks/{id}/status | TaskStatus | ||
/featuresOfInterest (fois) | Feature[] as GeoJSON | uid, text, type, geo, creation time, data time, proc, obsprop | |
/featuresOfInterest/{id} | Feature as GeoJSON | ||
/observations (obs) | Observation[] as OM-JSON | time, proc, foi, obsprop, geo | |
/observations/{id} | Observation as OM-JSON |
(*) idx is 0 for latest, and increment as we're going back in time
(**) reserved data stream names: 'location', 'status'
Paging and counting is allowed on all collections (i.e. procedures, descriptionHistory, fois, observations, records). Paging can be controlled by client using pageSize and pageToken query args, but the server can also impose a limit on the page size.
Counting Example: http://endpoint/observations/count?time=2017-01-01/2017-02-01
Service Info
{
"title": "service title",
"abstract": "service abstract",
"keywords": [],
"serviceType": "SOS",
"version": "2.0.0",
"profiles": [],
"fees": "",
"accessConstraints": "",
"provider": {
"name": "company name",
"contactInfo": {
"individualName": "Bob Jones",
"address": {
...
}
}
},
"creationTime": "2017-01-01T12:30:00Z",
"lastModified": "2017-01-01T12:30:00Z",
"links": {
"self": "http://.../",
"procedures": "http://.../procedures",
"featuresOfInterest": "http://.../fois",
"observations": "http://.../obs"
}
}
Procedure
{
"id": "unique integer id assigned by server",
"uid": "urn:org:sensor:001",
"name": "Temp Network",
"description": "Network of air temperature sensors deployed across the city",
"type": "device/device group/processing/processing group",
"tags": [],
"observableProperties": [],
"observedArea": {
"type": "Polygon",
"coordinates": [[
[100.0, 0.0],
[101.0, 0.0],
[101.0, 1.0],
[100.0, 0.0]
]]
},
"observationTypes": [],
"creationTime": "2017-01-01T12:30:00Z",
"lastModified": "2017-01-01T12:30:00Z",
"links": {
"self": "http://.../procedures/56",
"descriptionHistory": "http://.../procedures/56/desc",
"featuresOfInterest": "http://.../procedures/56/fois",
"observations": "http://.../procedures/56/obs",
"dataStreams": "http://.../procedures/56/streams"
}
}
AbstractProcess
A SML-JSON SimpleProcess, AggregateProcess, PhysicalComponent or PhysicalSystem object
Feature
A GeoJSON Feature object
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [102.0, 0.5]
},
"properties": {
"prop0": "value0"
},
"creationTime": "2017-01-01T12:30:00Z",
"lastModified": "2017-01-01T12:30:00Z"
}
DataStream
{
"numId": "1",
"name": "weather",
"components": {
"type": "DataRecord",
...
},
"encodings": [
"text/csv",
"application/json"
]
}
Task
{
"numId": "1",
"creationTime": "2017-01-01T12:30:00Z",
"lastModified": "2017-01-01T12:30:00Z",
"status": {
"estimatedToC": "2017-04-23T12:23:12Z",
"lastEvent": "",
"percentCompletion": "50",
"procedure": "urn:sensor:0001",
"requestStatus": "ACCEPTED",
"statusMessage": "no problem so far",
"taskStatus": "IN-PROGRESS",
"updateTime": "2017-04-22T12:00:00Z",
"taskingInput": "input id",
"taskingParameters": {
"pan": 12.5,
"tilt": -15.6
}
}
}
New resources are created with a POST request on the parent collection, and updated with PUT or PATCH.
Resources are deleted with a DELETE request using the ID or a filter on the collection
Follow OData or OpenSearch convention?
fois?bbox=lat,lon,lat,lon
streams/weather/historical?time=iso/iso streams/weather/realtime
Websocket connections can be made on */dataStreams/{id}/live
URLs with the same filter as regular HTTP connections. (In the core, only HTTP streaming connections are possible on live stream URLs).
The replay extension allows HTTP streaming and websocket connections on */streams/{id}/past
URLs to replay data at a particular speed.
Websocket connections can also be used for tasking by connecting to */commandInputs/{id}/live
URLs with an authorized task/session ID. Websocket allows for text/csv and binary encoded tasking messages.
Websocket connections are also possible on collections to get notified of additions/deletions/updates and on individual objects for deletions/updates.
Displaying live data from multiple sensors in a dashboard requires many statefull Websocket connections with the server. Multiplexing Websocket connections could be an efficient way to achieve it.
It could be done by sending messages from client to server indicating what streams to connect/disconnect as maps of IDs to URLs:
{
"connect": {
"1": "org-name/procedures/1563/streams/1/live",
"2": "org-name/procedures/569/streams/1/live",
"3": "org-name/procedures/33/streams/1/live"
}
}
The server would then respond by multiplexing all messages in the same connection prefixing them with a 2-bytes message ID, corresponding to the index in the array.
It would even be possible to connect and/or disconnect sources dynamically w/o closing the websocket connection:
{
connect": {
"4": "procedures/111/streams/1/live"
},
disconnect: ["1", "2"]
}
URL paths could be relative to where the initial WS request was sent (i.e. at the root vs. on a particular procedure)
MQTT connections can be made by using the URL path (up to the stream id) as the SUBSCRIBE topic (e.g. "org-name/procedures/temp_network/streams/temp"