Documentation
¶
Overview ¶
Package oms provides the OGC OMS v3.0 Observation document payload type for SemStreams. It is the bidirectional mapper between OMS-natural JSON (the wire shape every Connected Systems API consumer exchanges) and the SemStreams message.BaseMessage envelope that downstream processors route through the payload registry.
What it ships ¶
- Observation — the OGC OMS v3.0 Observation Go struct. Implements message.Payload (Schema / Validate / MarshalJSON / UnmarshalJSON) and [graph.Graphable] (EntityID / Triples).
- FeatureOfInterest — accepts either a URI reference or an inline GeoJSON Feature (via Phase 3 graph/geo/geojson).
- RegisterPayloads — registers ogc.oms.v3 with the payload registry. Aggregated into payloadbuiltins so every production binary picks it up automatically.
Schema identity ¶
The payload Schema is fixed at Type{Domain: "ogc", Category: "oms", Version: "v3"} — abbreviated as "ogc.oms.v3" in registry diagnostics and reactive-rule predicate matching.
Wire shape ¶
Observation.MarshalJSON emits the OMS-natural JSON document per OGC 20-082r4 bundled with CS API v1.0:
{
"type": "Observation",
"id": "observation-7f3a",
"procedure": "http://example.org/procedures/voltmeter",
"observedProperty": "http://example.org/properties/voltage",
"featureOfInterest": "http://example.org/features/battery-001",
"phenomenonTime": "2026-05-15T14:30:00Z",
"resultTime": "2026-05-15T14:30:00Z",
"result": 12.4
}
The BaseMessage envelope around an Observation places that JSON in the "payload" field of the SemStreams [message.wireFormat], so the same OMS-natural bytes flow through internal NATS publishes via message.NewDecoder without re-encoding.
Scope ¶
MVP coverage targets the CS API v1.0 critical path:
- Result as a simple JSON value (number, string, boolean). Quantity (value + uom), Category, and TimeSeries result shapes are deferred — operators producing typed results today should bind their UoM via the SensorML side (Phase 5) or via downstream processors.
- PhenomenonTime / ResultTime as ISO 8601 instants only. Time intervals ({begin, end}) deferred.
- FeatureOfInterest as either a URI reference or an inline GeoJSON Feature. Other OGC reference shapes deferred.
- Parameter, ValidTime, ResultQuality, RelatedObservation — all deferred. Operators needing these should file a follow-up.
See [ADR-044] for the framework / sister-repo split rationale and the dependency chain that places this package in Phase 6.
External references ¶
- OGC 20-082r4 OMS v3.0: https://docs.ogc.org/as/20-082r4/20-082r4.html
- CS API Part 2 (dynamic data): https://docs.ogc.org/DRAFTS/23-002r0.html
[graph.Graphable]: ../../graph [ADR-044]: ../../docs/adr/044-ogc-connected-systems-framework-split.md
Index ¶
Constants ¶
const ( // PredType is the rdf:type assertion (sosa:Observation IRI). PredType = "oms.observation.type" // PredHasFeatureOfInterest binds the observation to the // SOSA FeatureOfInterest it is about. Maps to // sosa:hasFeatureOfInterest. PredHasFeatureOfInterest = "oms.observation.hasFeatureOfInterest" // PredObservedProperty binds the observation to the SOSA // ObservableProperty it measured. Maps to // sosa:observedProperty. PredObservedProperty = "oms.observation.observedProperty" // PredUsedProcedure binds the observation to the SOSA // Procedure that produced it. Maps to sosa:usedProcedure. PredUsedProcedure = "oms.observation.usedProcedure" // PredResultTime carries the ISO 8601 resultTime. Maps to // sosa:resultTime. PredResultTime = "oms.observation.resultTime" // PredPhenomenonTime carries the ISO 8601 phenomenonTime. // Maps to sosa:phenomenonTime. PredPhenomenonTime = "oms.observation.phenomenonTime" // PredHasSimpleResult carries the simple literal Result. // Maps to sosa:hasSimpleResult. PredHasSimpleResult = "oms.observation.hasSimpleResult" )
Dotted-name predicate constants for the SemStreams convention. Each is registered to its SOSA IRI at init time so RDF/Turtle export through vocabulary/export emits the compacted sosa: forms. Mirrors parser/sensorml's predicates.go pattern.
const TypeObservation = "Observation"
TypeObservation is the JSON "type" discriminator value for OMS Observation documents per OGC 20-082r4.
Variables ¶
This section is empty.
Functions ¶
func RegisterPayloads ¶
func RegisterPayloads(reg *payloadregistry.Registry) error
RegisterPayloads registers the ogc.oms.v3 Observation payload with the supplied registry. Called from github.com/c360studio/semstreams/payloadbuiltins.Register at process bootstrap so every production binary picks up the type without extra wiring.
Mirrors the message.RegisterPayloads / agentic.RegisterPayloads shape so the bootstrap aggregator can call this uniformly.
func SchemaType ¶
SchemaType returns the registered payload type for OMS Observations. Useful for callers building a BaseMessage without first constructing the Observation struct.
Types ¶
type FeatureOfInterest ¶
type FeatureOfInterest struct {
// Href is set when the FoI is a bare URI reference.
Href string
// Feature is set when the FoI is an inline GeoJSON Feature.
Feature *geojson.Feature
}
FeatureOfInterest is either a URI reference to an external feature definition or an inline GeoJSON Feature carrying the spatial extent. Marshaling produces the URI string for the URI case and the GeoJSON object for the inline case; unmarshaling detects the shape and populates the right field.
func NewFeatureOfInterestFeature ¶
func NewFeatureOfInterestFeature(f *geojson.Feature) *FeatureOfInterest
NewFeatureOfInterestFeature constructs an inline-GeoJSON FeatureOfInterest.
func NewFeatureOfInterestRef ¶
func NewFeatureOfInterestRef(uri string) *FeatureOfInterest
NewFeatureOfInterestRef constructs a URI-shaped FeatureOfInterest.
func (*FeatureOfInterest) MarshalJSON ¶
func (f *FeatureOfInterest) MarshalJSON() ([]byte, error)
MarshalJSON emits either the bare URI string or the inline GeoJSON Feature shape, depending on which field is populated. When both are populated, Feature wins (the inline payload is strictly more informative). When neither is populated, emits JSON null.
func (*FeatureOfInterest) UnmarshalJSON ¶
func (f *FeatureOfInterest) UnmarshalJSON(data []byte) error
UnmarshalJSON dispatches on the JSON shape: a bare string becomes the Href; a JSON object becomes the inline Feature. JSON null leaves the value unset.
type Observation ¶
type Observation struct {
// ID is the local identifier for the observation. Required
// when downstream consumers need to address the observation
// individually; OMS itself does not mandate it.
ID string `json:"id,omitempty"`
// Procedure is the IRI of the SOSA Procedure / SensorML
// process that produced the observation.
Procedure string `json:"procedure"`
// ObservedProperty is the IRI of the SOSA ObservableProperty
// being measured.
ObservedProperty string `json:"observedProperty"`
// FeatureOfInterest is either a URI reference or an inline
// GeoJSON Feature carrying the spatial extent.
FeatureOfInterest *FeatureOfInterest `json:"featureOfInterest,omitempty"`
// PhenomenonTime is the time the phenomenon being observed
// occurred (ISO 8601 instant). Optional — when absent OMS
// permits consumers to fall back to ResultTime.
PhenomenonTime string `json:"phenomenonTime,omitempty"`
// ResultTime is the time the result was produced (ISO 8601
// instant). Required by OMS for every Observation.
ResultTime string `json:"resultTime"`
// Result is the observed value. Phase 6 MVP carries it as a
// plain JSON value (number, string, boolean). Quantity,
// Category, and TimeSeries results are deferred to follow-
// up tags.
//
// JSON round-trip canonicalizes all numeric results to
// float64 per encoding/json's default. Operators producing
// integer-valued OMS results that need to preserve int64
// fidelity through a round-trip should either (a) emit the
// result as a string and convert at consumption, or (b)
// wait for the typed Quantity / Category result envelopes
// that land in a follow-up tag.
Result any `json:"result,omitempty"`
}
Observation is the OGC OMS v3.0 Observation document. Fields mirror the JSON encoding bundled with CS API v1.0. Pointer- typed optional fields distinguish "absent" from "empty".
The struct implements message.Payload (see payload.go) and [graph.Graphable] (see graphable.go) so it can be carried by a BaseMessage envelope and contribute triples to the graph pipeline.
func (*Observation) EntityID ¶
func (o *Observation) EntityID() string
EntityID implements [graph.Graphable]. Returns the Observation's local ID — operators routing through the graph pipeline are expected to either populate the ID field with a 6-part SemStreams entity ID or rebind via a wrapping payload. Returns the empty string when ID is unset; downstream graph-ingest treats that as "no entity," which is the right fall-through for ingest pipelines doing entity resolution from triples instead of the local ID.
func (*Observation) MarshalJSON ¶
func (o *Observation) MarshalJSON() ([]byte, error)
MarshalJSON emits the OMS-natural JSON document shape per OGC 20-082r4. OMS v3.0 carries a "type" discriminator on the wire for forward-compatibility with sibling shapes (Sample, ObservationCollection, …) that this Go package does not yet implement; the constant is emitted unconditionally because the Go type can only represent the Observation case. Avoids the infinite-recursion footgun by aliasing.
func (*Observation) Schema ¶
func (o *Observation) Schema() message.Type
Schema implements message.Payload. Always returns ogc.oms.v3.
func (*Observation) Triples ¶
func (o *Observation) Triples() []message.Triple
Triples implements [graph.Graphable]. Emits the SOSA-aligned triple set for this observation:
- rdf:type → sosa:Observation
- sosa:usedProcedure → procedure IRI
- sosa:observedProperty → property IRI
- sosa:hasFeatureOfInterest → FoI IRI (URI ref case) or a synthetic inline-Feature subject (deferred)
- sosa:resultTime → ISO 8601 timestamp
- sosa:phenomenonTime → ISO 8601 timestamp (when present)
- sosa:hasSimpleResult → the literal result value
Inline-GeoJSON FoIs emit a single hasFeatureOfInterest triple pointing at the GeoJSON Feature's id (or empty when the Feature has no id). Richer per-Feature triples would require a second-pass entity emission and are deferred — the graph pipeline can pick up the inline Feature via a dedicated processor.
func (*Observation) UnmarshalJSON ¶
func (o *Observation) UnmarshalJSON(data []byte) error
UnmarshalJSON parses the OMS-natural JSON document, validating the type discriminator before populating the struct fields.
func (*Observation) Validate ¶
func (o *Observation) Validate() error
Validate implements message.Payload. Enforces OMS v3.0's required fields: Procedure, ObservedProperty, ResultTime. Optional fields with present-but-invalid values surface as validation errors.