-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathobservation.go
205 lines (173 loc) · 6.47 KB
/
observation.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
package core
import (
"encoding/json"
"errors"
"fmt"
"time"
"strings"
)
const (
// ISO8601 defines the ISO8601 date time format
ISO8601 = "2006-01-02T15:04:05.999Z07:00"
)
// Observation in SensorThings represents a single Sensor reading of an ObservedProperty. A physical device, a Sensor, sends
// Observations to a specified Datastream. An Observation requires a FeatureOfInterest entity, if none is provided in the request,
// the Location of the Thing associated with the Datastream, will be assigned to the new Observation as the FeaturOfInterest.
type Observation struct {
BaseEntity
PhenomenonTime string `json:"phenomenonTime,omitempty"`
Result json.RawMessage `json:"result,omitempty"`
ResultTime *string `json:"resultTime,omitempty"`
ResultQuality string `json:"resultQuality,omitempty"`
ValidTime string `json:"validTime,omitempty"`
Parameters map[string]interface{} `json:"parameters,omitempty"`
NavDatastream string `json:"[email protected],omitempty"`
NavFeatureOfInterest string `json:"[email protected],omitempty"`
Datastream *Datastream `json:"Datastream,omitempty"`
FeatureOfInterest *FeatureOfInterest `json:"FeatureOfInterest,omitempty"`
}
func (o *Observation) ClearNav() {
o.NavSelf = ""
o.NavDatastream = ""
o.NavFeatureOfInterest = ""
}
// GetEntityType returns the EntityType for Observation
func (o Observation) GetEntityType() EntityType {
return EntityTypeObservation
}
// GetPropertyNames returns the available properties for an Observation
func (o *Observation) GetPropertyNames() []string {
return []string{"id", "phenomenonTime", "result", "resultTime", "resultQuality", "validTime", "parameters"}
}
// ParseEntity tries to parse the given json byte array into the current entity
func (o *Observation) ParseEntity(data []byte) error {
observation := &o
err := json.Unmarshal(data, observation)
if err != nil {
return errors.New("Unable to parse Observation")
}
return nil
}
// ContainsMandatoryParams checks if all mandatory params for Observation are available before posting.
func (o *Observation) ContainsMandatoryParams() (bool, []error) {
// When a SensorThings service receives a POST Observations without phenomenonTime, the service SHALL
// assign the current server time to the value of the phenomenonTime.
var errors []error
err := o.setPhenomenonTime()
if err != nil {
errors = append(errors, err)
}
// When a SensorThings service receives a POST Observations without resultTime, the service SHALL assign a
// null value to the resultTime.
if o.ResultTime != nil {
rt := *o.ResultTime
if t, err := time.Parse(ISO8601, rt); err != nil {
errors = append(errors, fmt.Errorf("Invalid resultTime: %v", err.Error()))
} else {
rt = t.UTC().Format("2006-01-02T15:04:05.000Z")
t, _ = time.Parse(ISO8601, rt)
}
}
CheckMandatoryParam(&errors, o.PhenomenonTime, o.GetEntityType(), "phenomenonTime")
CheckMandatoryParam(&errors, o.Result, o.GetEntityType(), "result")
CheckMandatoryParam(&errors, o.Datastream, o.GetEntityType(), "Datastream")
if len(errors) != 0 {
return false, errors
}
return true, nil
}
func (o *Observation) setPhenomenonTime() error {
if len(o.PhenomenonTime) == 0 {
o.PhenomenonTime = time.Now().UTC().Format(ISO8601)
} else {
splitTime := strings.Split(o.PhenomenonTime, "/")
timeString, err := parseTime("", splitTime[0])
if err != nil {
return err
}
if(len(splitTime) > 1){
timeString, err = parseTime(fmt.Sprintf("%s/", timeString), splitTime[1])
if err != nil {
return err
}
}
o.PhenomenonTime = timeString
}
return nil
}
func parseTime(prefix, timeString string) (string, error) {
parsedString := ""
if t, err := time.Parse(ISO8601, timeString); err != nil {
return parsedString, fmt.Errorf("Invalid phenomenonTime: %v", err.Error())
} else {
parsedString = fmt.Sprintf("%s%s", prefix, t.UTC().Format("2006-01-02T15:04:05.000Z"))
}
return parsedString, nil
}
// MarshalJSON marshalls the observation into a JSON byte array
func (o *Observation) MarshalJSON() ([]byte, error) {
if o.ResultTime != nil {
rt := o.ResultTime
if len(*o.ResultTime) == 0 {
rt = nil
}
return json.Marshal(struct {
Observation
ResultTime *string `json:"resultTime"`
}{
Observation: *o,
ResultTime: rt,
})
}
return json.Marshal(struct {
Observation
}{
Observation: *o,
})
}
// SetAllLinks sets the self link and relational links
func (o *Observation) SetAllLinks(externalURL string) {
o.SetSelfLink(externalURL)
o.SetLinks(externalURL)
if o.Datastream != nil {
o.Datastream.SetAllLinks(externalURL)
}
if o.FeatureOfInterest != nil {
o.FeatureOfInterest.SetAllLinks(externalURL)
}
}
// SetSelfLink sets the self link for the entity
func (o *Observation) SetSelfLink(externalURL string) {
o.NavSelf = CreateEntitySelfLink(externalURL, EntityLinkObservations.ToString(), o.ID)
}
// SetLinks sets the entity specific navigation links, empty string if linked(expanded) data is not nil
func (o *Observation) SetLinks(externalURL string) {
o.NavDatastream = CreateEntityLink(o.Datastream == nil, externalURL, EntityLinkObservations.ToString(), EntityTypeDatastream.ToString(), o.ID)
o.NavFeatureOfInterest = CreateEntityLink(o.FeatureOfInterest == nil, externalURL, EntityLinkObservations.ToString(), EntityTypeFeatureOfInterest.ToString(), o.ID)
}
// MarshalPostgresJSON marshalls an observation entity for saving into PostgreSQL
func (o Observation) MarshalPostgresJSON() ([]byte, error) {
rt := ""
if o.ResultTime != nil {
rt = *o.ResultTime
}
return json.Marshal(&struct {
PhenomenonTime string `json:"phenomenonTime,omitempty"`
Result json.RawMessage `json:"result,omitempty"`
ResultTime string `json:"resultTime,omitempty"`
ResultQuality string `json:"resultQuality,omitempty"`
ValidTime string `json:"validTime,omitempty"`
Parameters map[string]interface{} `json:"parameters,omitempty"`
}{
PhenomenonTime: o.PhenomenonTime,
Result: o.Result,
ResultTime: rt,
ResultQuality: o.ResultQuality,
ValidTime: o.ValidTime,
Parameters: o.Parameters,
})
}
// GetSupportedEncoding returns the supported encoding tye for this entity
func (o Observation) GetSupportedEncoding() map[int]EncodingType {
return map[int]EncodingType{}
}