func fieldThresholdProto(r *http.Request, h http.Header, b *bytes.Buffer) *weft.Result { var err error var rows *sql.Rows if rows, err = dbR.Query(`SELECT deviceID, typeID, lower, upper, scale FROM field.threshold JOIN field.device USING (devicepk) JOIN field.type USING (typepk)`); err != nil { return weft.InternalServerError(err) } var ts mtrpb.FieldMetricThresholdResult for rows.Next() { var t mtrpb.FieldMetricThreshold if err = rows.Scan(&t.DeviceID, &t.TypeID, &t.Lower, &t.Upper, &t.Scale); err != nil { return weft.InternalServerError(err) } ts.Result = append(ts.Result, &t) } var by []byte if by, err = proto.Marshal(&ts); err != nil { return weft.InternalServerError(err) } b.Write(by) return &weft.StatusOK }
func dataCompletenessDelete(r *http.Request, h http.Header, b *bytes.Buffer) *weft.Result { v := r.URL.Query() siteID := v.Get("siteID") typeID := v.Get("typeID") var txn *sql.Tx var err error if txn, err = db.Begin(); err != nil { return weft.InternalServerError(err) } for _, table := range []string{"data.completeness", "data.completeness_summary", "data.completeness_tag"} { if _, err = txn.Exec(`DELETE FROM `+table+` WHERE sitePK = (SELECT sitePK FROM data.site WHERE siteID = $1) AND typePK = (SELECT typePK FROM data.completeness_type WHERE typeID = $2)`, siteID, typeID); err != nil { txn.Rollback() return weft.InternalServerError(err) } } if err = txn.Commit(); err != nil { return weft.InternalServerError(err) } return &weft.StatusOK }
func fieldModelProto(r *http.Request, h http.Header, b *bytes.Buffer) *weft.Result { var err error var rows *sql.Rows if rows, err = dbR.Query(`SELECT modelID FROM field.model`); err != nil { return weft.InternalServerError(err) } var fmr mtrpb.FieldModelResult for rows.Next() { var t mtrpb.FieldModel if err = rows.Scan(&t.ModelID); err != nil { return weft.InternalServerError(err) } fmr.Result = append(fmr.Result, &t) } var by []byte if by, err = proto.Marshal(&fmr); err != nil { return weft.InternalServerError(err) } b.Write(by) return &weft.StatusOK }
func dataCompletenessTypeProto(r *http.Request, h http.Header, b *bytes.Buffer) *weft.Result { var err error var rows *sql.Rows if rows, err = dbR.Query(`SELECT typeID FROM data.completeness_type ORDER BY typeID ASC`); err != nil { return weft.InternalServerError(err) } defer rows.Close() var ftr mtrpb.DataTypeResult for rows.Next() { var ft mtrpb.DataType if err = rows.Scan(&ft.TypeID); err != nil { return weft.InternalServerError(err) } ftr.Result = append(ftr.Result, &ft) } var by []byte if by, err = proto.Marshal(&ftr); err != nil { return weft.InternalServerError(err) } b.Write(by) return &weft.StatusOK }
// handler that serves an html page for detailed metric information func metricDetailHandler(r *http.Request, h http.Header, b *bytes.Buffer) *weft.Result { var ( err error ) if res := weft.CheckQuery(r, []string{"deviceID", "typeID"}, []string{}); !res.Ok { return res } // We create a page struct with variables to substitute into the loaded template q := r.URL.Query() deviceID := q.Get("deviceID") typeID := q.Get("typeID") p := metricDetailPage{MtrApiUrl: mtrApiUrl} p.Border.Title = fmt.Sprintf("Detailed Metric Info for deviceID:%s TypeID:%s", deviceID, typeID) p.MetricDetail.DeviceID = deviceID p.MetricDetail.TypeID = typeID if err = p.populateTags(); err != nil { return weft.InternalServerError(err) } if err = metricDetailTemplate.ExecuteTemplate(b, "border", p); err != nil { return weft.InternalServerError(err) } return &weft.StatusOK }
func fieldMetricDelete(r *http.Request, h http.Header, b *bytes.Buffer) *weft.Result { v := r.URL.Query() deviceID := v.Get("deviceID") typeID := v.Get("typeID") var err error var txn *sql.Tx if txn, err = db.Begin(); err != nil { return weft.InternalServerError(err) } for _, table := range []string{"field.metric", "field.metric_summary", "field.metric_tag", "field.threshold"} { if _, err = txn.Exec(`DELETE FROM `+table+` WHERE devicePK = (SELECT devicePK FROM field.device WHERE deviceID = $1) AND typePK = (SELECT typePK from field.type WHERE typeID = $2)`, deviceID, typeID); err != nil { txn.Rollback() return weft.InternalServerError(err) } } if err = txn.Commit(); err != nil { return weft.InternalServerError(err) } return &weft.StatusOK }
func fieldPageHandler(r *http.Request, h http.Header, b *bytes.Buffer) *weft.Result { var err error if res := weft.CheckQuery(r, []string{}, []string{}); !res.Ok { return res } p := mtrUiPage{} p.Path = r.URL.Path p.Border.Title = "GeoNet MTR" p.ActiveTab = "Field" if err = p.populateTags(); err != nil { return weft.InternalServerError(err) } var pa panel if pa, err = getFieldSummary(); err != nil { return weft.InternalServerError(err) } p.Panels = []panel{pa} if err = fieldTemplate.ExecuteTemplate(b, "border", p); err != nil { return weft.InternalServerError(err) } return &weft.StatusOK }
//search tags and place names from devices func tagsProto(r *http.Request, h http.Header, b *bytes.Buffer) *weft.Result { var err error var rows *sql.Rows if rows, err = dbR.Query(`SELECT DISTINCT tag from ((SELECT tag FROM mtr.tag ) union (SELECT CASE WHEN strpos(deviceid, '-') = 0 THEN deviceid ELSE split_part(deviceid, '-', 2) END AS tag FROM field.device) union (SELECT siteid from data.site as tag)) ts ORDER BY tag ASC`); err != nil { return weft.InternalServerError(err) } defer rows.Close() var ts mtrpb.TagResult for rows.Next() { var t mtrpb.Tag if err = rows.Scan(&t.Tag); err != nil { return weft.InternalServerError(err) } ts.Result = append(ts.Result, &t) } var by []byte if by, err = proto.Marshal(&ts); err != nil { return weft.InternalServerError(err) } b.Write(by) return &weft.StatusOK }
func searchPageHandler(r *http.Request, h http.Header, b *bytes.Buffer) *weft.Result { var err error var p *searchPage if res := weft.CheckQuery(r, []string{"tagQuery"}, []string{"page"}); !res.Ok { return res } r.ParseForm() tagQuery := r.FormValue("tagQuery") // Javascript should handle empty query value // Non existent value comes from unauthorized submit if tagQuery == "" { return weft.BadRequest("missing required query parameter: tagQuery") } if p, err = newSearchPage(mtrApiUrl); err != nil { return weft.BadRequest("error creating searchPage object") } if err = p.populateTags(); err != nil { return weft.InternalServerError(err) } if err = p.matchingMetrics(tagQuery); err != nil { return weft.InternalServerError(err) } if err := tagSearchTemplate.ExecuteTemplate(b, "border", p); err != nil { return weft.InternalServerError(err) } return &weft.StatusOK }
func dataPageHandler(r *http.Request, h http.Header, b *bytes.Buffer) *weft.Result { var err error if res := weft.CheckQuery(r, []string{}, []string{}); !res.Ok { return res } // We create a page struct with variables to substitute into the loaded template p := mtrUiPage{} p.Path = r.URL.Path p.Border.Title = "GeoNet MTR - Data" p.ActiveTab = "Data" if err = p.populateTags(); err != nil { return weft.InternalServerError(err) } var pa panel if pa, err = getDataSummary(); err != nil { return weft.InternalServerError(err) } p.Panels = []panel{pa} if err = dataTemplate.ExecuteTemplate(b, "border", p); err != nil { return weft.InternalServerError(err) } return &weft.StatusOK }
// write a protobuf to b of all applicationid's in app.application func appIdProto(r *http.Request, h http.Header, b *bytes.Buffer) *weft.Result { var err error var rows *sql.Rows if rows, err = dbR.Query(`SELECT applicationid FROM app.application ORDER BY applicationid ASC`); err != nil { return weft.InternalServerError(err) } defer rows.Close() var ar mtrpb.AppIDSummaryResult for rows.Next() { var ai mtrpb.AppIDSummary if err = rows.Scan(&ai.ApplicationID); err != nil { return weft.InternalServerError(err) } ar.Result = append(ar.Result, &ai) } var by []byte if by, err = proto.Marshal(&ar); err != nil { return weft.InternalServerError(err) } b.Write(by) return &weft.StatusOK }
func dataCompletenessTagProto(r *http.Request, h http.Header, b *bytes.Buffer) *weft.Result { var err error var rows *sql.Rows if rows, err = dbR.Query(`SELECT siteID, tag, typeID from data.completeness_tag JOIN mtr.tag USING (tagpk) JOIN data.site USING (sitepk) JOIN data.completeness_type USING (typepk) ORDER BY tag ASC`); err != nil { return weft.InternalServerError(err) } defer rows.Close() var ts mtrpb.DataCompletenessTagResult for rows.Next() { var t mtrpb.DataCompletenessTag if err = rows.Scan(&t.SiteID, &t.Tag, &t.TypeID); err != nil { return weft.InternalServerError(err) } ts.Result = append(ts.Result, &t) } var by []byte if by, err = proto.Marshal(&ts); err != nil { return weft.InternalServerError(err) } b.Write(by) return &weft.StatusOK }
// Contruct a simple page that has several plots (and time intervals as param) for the specified applicationID param func appPlotPageHandler(r *http.Request, h http.Header, b *bytes.Buffer) *weft.Result { var err error if res := weft.CheckQuery(r, []string{"applicationID"}, []string{"resolution", "interactive"}); !res.Ok { return res } p := mtrUiPage{} p.Path = r.URL.Path p.MtrApiUrl = mtrApiUrl.String() p.Border.Title = "GeoNet MTR - application ID" p.ActiveTab = "Apps" // get the applicationID and resolution params from the URL p.pageParam(r.URL.Query()) // Resolution not required if we're in "interactive" mode otherwise default is minute if p.Resolution == "" && !p.Interactive { p.Resolution = "minute" } if err = p.populateTags(); err != nil { return weft.InternalServerError(err) } if err = appPlotTemplate.ExecuteTemplate(b, "border", p); err != nil { return weft.InternalServerError(err) } return &weft.StatusOK }
func fieldMetricTagPut(r *http.Request, h http.Header, b *bytes.Buffer) *weft.Result { v := r.URL.Query() var err error var result sql.Result if result, err = db.Exec(`INSERT INTO field.metric_tag(devicePK, typePK, tagPK) SELECT devicePK, typePK, tagPK FROM field.device, field.type, mtr.tag WHERE deviceID = $1 AND typeID = $2 AND tag = $3`, v.Get("deviceID"), v.Get("typeID"), v.Get("tag")); err != nil { if err, ok := err.(*pq.Error); ok && err.Code == errorUniqueViolation { // ignore unique constraint errors return &weft.StatusOK } else { return weft.InternalServerError(err) } } var i int64 if i, err = result.RowsAffected(); err != nil { return weft.InternalServerError(err) } if i != 1 { return weft.BadRequest("Didn't create row, check your query parameters exist") } return &weft.StatusOK }
func dataSitesPageHandler(r *http.Request, h http.Header, b *bytes.Buffer) *weft.Result { var err error if res := weft.CheckQuery(r, []string{}, []string{"status", "typeID"}); !res.Ok { return res } p := mtrUiPage{} p.Path = r.URL.Path p.Border.Title = "GeoNet MTR - Data Sites" p.ActiveTab = "Data" p.MtrApiUrl = mtrApiUrl.String() if err = p.populateTags(); err != nil { return weft.InternalServerError(err) } p.pageParam(r.URL.Query()) if err = p.getSitesList(); err != nil { return weft.InternalServerError(err) } if err = dataTemplate.ExecuteTemplate(b, "border", p); err != nil { return weft.InternalServerError(err) } return &weft.StatusOK }
func fieldDeviceProto(r *http.Request, h http.Header, b *bytes.Buffer) *weft.Result { var err error var rows *sql.Rows if rows, err = dbR.Query(`SELECT deviceid, modelid, latitude, longitude FROM field.device JOIN field.model USING(modelpk)`); err != nil { return weft.InternalServerError(err) } var fdr mtrpb.FieldDeviceResult for rows.Next() { var d mtrpb.FieldDevice if err = rows.Scan(&d.DeviceID, &d.ModelID, &d.Latitude, &d.Longitude); err != nil { return weft.InternalServerError(err) } fdr.Result = append(fdr.Result, &d) } var by []byte if by, err = proto.Marshal(&fdr); err != nil { return weft.InternalServerError(err) } b.Write(by) return &weft.StatusOK }
// Proxies sensor *.geojson from S3 func sensorV2(r *http.Request, h http.Header, b *bytes.Buffer) *weft.Result { if res := weft.CheckQuery(r, []string{"type"}, []string{}); !res.Ok { return res } t := r.URL.Query().Get("type") if !sensorGeoJSON[t] { return &weft.NotFound } params := &s3.GetObjectInput{ Key: aws.String("delta/" + t + ".geojson"), Bucket: aws.String("api.geonet.org.nz"), } res, err := s3Client.GetObject(params) if err != nil { return weft.InternalServerError(err) } defer res.Body.Close() _, err = b.ReadFrom(res.Body) if err != nil { return weft.InternalServerError(err) } h.Set("Content-Type", V2GeoJSON) h.Set("Surrogate-Control", maxAge3600) return &weft.StatusOK }
func dataSiteProto(r *http.Request, h http.Header, b *bytes.Buffer) *weft.Result { var err error var rows *sql.Rows if rows, err = dbR.Query(`SELECT siteID, latitude, longitude FROM data.site`); err != nil { return weft.InternalServerError(err) } var ts mtrpb.DataSiteResult for rows.Next() { var t mtrpb.DataSite if err = rows.Scan(&t.SiteID, &t.Latitude, &t.Longitude); err != nil { return weft.InternalServerError(err) } ts.Result = append(ts.Result, &t) } var by []byte if by, err = proto.Marshal(&ts); err != nil { return weft.InternalServerError(err) } b.Write(by) return &weft.StatusOK }
func dataLatencyThresholdPut(r *http.Request, h http.Header, b *bytes.Buffer) *weft.Result { v := r.URL.Query() var err error var lower, upper int if lower, err = strconv.Atoi(v.Get("lower")); err != nil { return weft.BadRequest("invalid lower") } if upper, err = strconv.Atoi(v.Get("upper")); err != nil { return weft.BadRequest("invalid upper") } siteID := v.Get("siteID") typeID := v.Get("typeID") var result sql.Result // TODO Change to upsert 9.5 // return if insert succeeds if result, err = db.Exec(`INSERT INTO data.latency_threshold(sitePK, typePK, lower, upper) SELECT sitePK, typePK, $3, $4 FROM data.site, data.type WHERE siteID = $1 AND typeID = $2`, siteID, typeID, lower, upper); err == nil { var i int64 if i, err = result.RowsAffected(); err != nil { return weft.InternalServerError(err) } if i == 1 { return &weft.StatusOK } } // return if update one row if pqErr, ok := err.(*pq.Error); ok && pqErr.Code == errorUniqueViolation { if result, err = db.Exec(`UPDATE data.latency_threshold SET lower=$3, upper=$4 WHERE sitePK = (SELECT sitePK FROM data.site WHERE siteID = $1) AND typePK = (SELECT typePK FROM data.type WHERE typeID = $2)`, siteID, typeID, lower, upper); err == nil { var i int64 if i, err = result.RowsAffected(); err != nil { return weft.InternalServerError(err) } if i == 1 { return &weft.StatusOK } } } if err == nil { err = fmt.Errorf("no rows affected, check your query.") } return weft.InternalServerError(err) }
func fieldLatestGeoJSON(r *http.Request, h http.Header, b *bytes.Buffer) *weft.Result { var rows *sql.Rows var err error typeID := r.URL.Query().Get("typeID") var d string err = db.QueryRow("select typeID FROM field.type where typeID = $1", typeID).Scan(&d) if err == sql.ErrNoRows { return &weft.NotFound } if err != nil { return weft.ServiceUnavailableError(err) } if rows, err = dbR.Query(` WITH p as (SELECT geom, time, value, lower, upper, deviceid, typeid FROM field.metric_summary JOIN field.device using (devicePK) JOIN field.threshold using (devicePK, typePK) JOIN field.type using (typePK) WHERE typeID = $1) SELECT row_to_json(fc) FROM ( SELECT 'FeatureCollection' as type, COALESCE(array_to_json(array_agg(f)), '[]') as features from (SELECT 'Feature' as type, ST_AsGeoJSON(p.geom)::json as geometry, row_to_json( (SELECT l FROM ( SELECT "time", value, lower, upper, deviceid, typeid ) as l ) ) as properties FROM p ) as f ) as fc`, typeID); err != nil { return weft.InternalServerError(err) } defer rows.Close() var gj string if rows.Next() { if err = rows.Scan(&gj); err != nil { return weft.InternalServerError(err) } } rows.Close() b.WriteString(gj) return &weft.StatusOK }
func mapPageHandler(r *http.Request, h http.Header, b *bytes.Buffer) *weft.Result { var err error if res := weft.CheckQuery(r, []string{}, []string{}); !res.Ok { return res } p := mapPage{} p.MtrApiUrl = mtrApiUrl.String() p.Border.Title = "GeoNet MTR - Map" p.ActiveTab = "Map" if err = p.populateTags(); err != nil { return weft.InternalServerError(err) } if err = p.populateTypes(); err != nil { return weft.InternalServerError(err) } s := strings.TrimPrefix(r.URL.Path, "/map") typeExist := false if ArrayContains(s, []string{"", "/"}) { p.TypeID = "" typeExist = true for _, mapdef := range p.Border.MapList { if len(mapdef.TypeIDs) > 0 { p.TypeID = mapdef.TypeIDs[0] p.MapApiUrl = mapdef.ApiUrl break } } } else { s1 := strings.TrimPrefix(s, "/") for _, mapdef := range p.Border.MapList { if ArrayContains(s1, mapdef.TypeIDs) { p.TypeID = s1 p.MapApiUrl = mapdef.ApiUrl typeExist = true break } } } if !typeExist { return weft.InternalServerError(fmt.Errorf("Unknown map type")) } if err = mapTemplate.ExecuteTemplate(b, "border", p); err != nil { return weft.InternalServerError(err) } return &weft.StatusOK }
// TODO: returns weft.NotFound when query result is empty? func fieldLatestProto(r *http.Request, h http.Header, b *bytes.Buffer) *weft.Result { typeID := r.URL.Query().Get("typeID") var err error var rows *sql.Rows switch typeID { case "": rows, err = dbR.Query(`select deviceID, modelID, typeid, time, value, lower, upper, scale FROM field.metric_summary JOIN field.device using (devicePK) JOIN field.model using (modelPK) JOIN field.threshold using (devicePK, typePK) JOIN field.type using (typePK)`) default: rows, err = dbR.Query(`select deviceID, modelID, typeid, time, value, lower, upper, scale FROM field.metric_summary JOIN field.device using (devicePK) JOIN field.model using (modelPK) JOIN field.threshold using (devicePK, typePK) JOIN field.type using (typePK) WHERE typeID = $1;`, typeID) } if err != nil { return weft.InternalServerError(err) } defer rows.Close() var t time.Time var fmlr mtrpb.FieldMetricSummaryResult for rows.Next() { var fmr mtrpb.FieldMetricSummary if err = rows.Scan(&fmr.DeviceID, &fmr.ModelID, &fmr.TypeID, &t, &fmr.Value, &fmr.Lower, &fmr.Upper, &fmr.Scale); err != nil { return weft.InternalServerError(err) } fmr.Seconds = t.Unix() fmlr.Result = append(fmlr.Result, &fmr) } rows.Close() var by []byte if by, err = proto.Marshal(&fmlr); err != nil { return weft.InternalServerError(err) } b.Write(by) return &weft.StatusOK }
/* spark draws an svg spark line to b. Assumes f.loadPK has been called first. */ func dataCompletenessSpark(siteID, typeID string, b *bytes.Buffer) *weft.Result { var p ts.Plot p.SetXAxis(time.Now().UTC().Add(time.Hour*-12), time.Now().UTC()) var err error var rows *sql.Rows var expected int var typePK int if err = dbR.QueryRow(`SELECT typePK, expected FROM data.completeness_type WHERE typeID = $1`, typeID).Scan(&typePK, &expected); err != nil { if err == sql.ErrNoRows { return &weft.NotFound } return weft.InternalServerError(err) } expectedf := float64(expected) if rows, err = dbR.Query(`SELECT date_trunc('hour',time) as t, sum(count) FROM data.completeness WHERE sitePK = (SELECT sitePK FROM data.site WHERE siteID = $1) AND typePK = $2 AND time > now() - interval '28 days' GROUP BY date_trunc('hour',time) ORDER BY t ASC`, siteID, typePK); err != nil { return weft.InternalServerError(err) } defer rows.Close() var pts []ts.Point for rows.Next() { var pt ts.Point var v int if err = rows.Scan(&pt.DateTime, &v); err != nil { return weft.InternalServerError(err) } // No need to scale spark data for display. pt.Value = float64(v) / expectedf pts = append(pts, pt) } if len(pts) > 0 { p.AddSeries(ts.Series{Colour: "deepskyblue", Points: pts}) } if err = ts.SparkLine.Draw(p, b); err != nil { return weft.InternalServerError(err) } return &weft.StatusOK }
func fieldDevicePut(r *http.Request, h http.Header, b *bytes.Buffer) *weft.Result { v := r.URL.Query() var err error var latitude, longitude float64 if latitude, err = strconv.ParseFloat(v.Get("latitude"), 64); err != nil { return weft.BadRequest("latitude invalid") } if longitude, err = strconv.ParseFloat(v.Get("longitude"), 64); err != nil { return weft.BadRequest("longitude invalid") } var result sql.Result // TODO - use upsert with PG 9.5? // return if insert succeeds if result, err = db.Exec(`INSERT INTO field.device(deviceID, modelPK, latitude, longitude) SELECT $1, modelPK, $3, $4 FROM field.model WHERE modelID = $2`, v.Get("deviceID"), v.Get("modelID"), latitude, longitude); err == nil { var i int64 if i, err = result.RowsAffected(); err != nil { return weft.InternalServerError(err) } if i == 1 { return &weft.StatusOK } } // return if update one row if pqErr, ok := err.(*pq.Error); ok && pqErr.Code == errorUniqueViolation { if result, err = db.Exec(`UPDATE field.device SET latitude = $2, longitude = $3 WHERE deviceID = $1`, v.Get("deviceID"), latitude, longitude); err == nil { var i int64 if i, err = result.RowsAffected(); err != nil { return weft.InternalServerError(err) } if i == 1 { return &weft.StatusOK } } } if err == nil { err = fmt.Errorf("no rows affected, check your query.") } return weft.InternalServerError(err) }
func tagPageHandler(r *http.Request, h http.Header, b *bytes.Buffer) *weft.Result { var err error if res := weft.CheckQuery(r, []string{}, []string{}); !res.Ok { return res } p := tagPage{} p.Path = r.URL.Path p.Border.Title = "GeoNet MTR" p.ActiveTab = "Tag" if err = p.populateTags(); err != nil { return weft.InternalServerError(err) } ph := strings.TrimPrefix(p.Path, "/tag") if strings.HasPrefix(ph, "/") { ph = ph[1:] } currTab := -1 // Create grouping tabs p.TagTabs = make([]string, 0) for i, k := range tagGrouper { s := k[:1] + "-" + k[len(k)-1:] p.TagTabs = append(p.TagTabs, s) if ph == s { currTab = i } } if currTab == -1 && ph != "" { return weft.BadRequest("Invalid tag index.") } if ph == "" { currTab = 0 } p.Path = p.TagTabs[currTab] for _, t := range p.Border.TagList { c := t[:1] if strings.Contains(tagGrouper[currTab], c) { p.Tags = append(p.Tags, t) } } if err = tagPageTemplate.ExecuteTemplate(b, "border", p); err != nil { return weft.InternalServerError(err) } return &weft.StatusOK }
// TODO: returns weft.NotFound when query result is empty? func dataLatencySummaryProto(r *http.Request, h http.Header, b *bytes.Buffer) *weft.Result { typeID := r.URL.Query().Get("typeID") var err error var rows *sql.Rows switch typeID { case "": rows, err = dbR.Query(`SELECT siteID, typeID, time, mean, fifty, ninety, lower, upper, scale FROM data.latency_summary JOIN data.site USING (sitePK) JOIN data.latency_threshold USING (sitePK, typePK) JOIN data.type USING (typePK)`) default: rows, err = dbR.Query(`SELECT siteID, typeID, time, mean, fifty, ninety, lower, upper, scale FROM data.latency_summary JOIN data.site USING (sitePK) JOIN data.latency_threshold USING (sitePK, typePK) JOIN data.type USING (typePK) WHERE typeID = $1;`, typeID) } if err != nil { return weft.InternalServerError(err) } defer rows.Close() var t time.Time var dlsr mtrpb.DataLatencySummaryResult for rows.Next() { var dls mtrpb.DataLatencySummary if err = rows.Scan(&dls.SiteID, &dls.TypeID, &t, &dls.Mean, &dls.Fifty, &dls.Ninety, &dls.Lower, &dls.Upper, &dls.Scale); err != nil { return weft.InternalServerError(err) } dls.Seconds = t.Unix() dlsr.Result = append(dlsr.Result, &dls) } rows.Close() var by []byte if by, err = proto.Marshal(&dlsr); err != nil { return weft.InternalServerError(err) } b.Write(by) return &weft.StatusOK }
func fieldMetricTagProto(r *http.Request, h http.Header, b *bytes.Buffer) *weft.Result { var err error var rows *sql.Rows deviceID := r.URL.Query().Get("deviceID") typeID := r.URL.Query().Get("typeID") if deviceID == "" && typeID == "" { if rows, err = dbR.Query(`SELECT deviceID, tag, typeID from field.metric_tag JOIN mtr.tag USING (tagpk) JOIN field.device USING (devicepk) JOIN field.type USING (typepk) ORDER BY tag ASC`); err != nil { return weft.InternalServerError(err) } defer rows.Close() } else if deviceID != "" && typeID != "" { if rows, err = dbR.Query(`SELECT deviceID, tag, typeID from field.metric_tag JOIN mtr.tag USING (tagpk) JOIN field.device USING (devicepk) JOIN field.type USING (typepk) WHERE deviceID=$1 AND typeID=$2 ORDER BY tag ASC`, deviceID, typeID); err != nil { return weft.InternalServerError(err) } defer rows.Close() } else { return weft.BadRequest("Invalid parameter. Please specify both deviceID and typeID.") } var ts mtrpb.FieldMetricTagResult for rows.Next() { var t mtrpb.FieldMetricTag if err = rows.Scan(&t.DeviceID, &t.Tag, &t.TypeID); err != nil { return weft.InternalServerError(err) } ts.Result = append(ts.Result, &t) } var by []byte if by, err = proto.Marshal(&ts); err != nil { return weft.InternalServerError(err) } b.Write(by) return &weft.StatusOK }
func getQuakesCsv(r *http.Request, h http.Header, b *bytes.Buffer) *weft.Result { //1. check query parameters if res := weft.CheckQuery(r, []string{}, optionalParams); !res.Ok { return res } v := r.URL.Query() //21 fields sqlString := `select format('%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s', publicid,eventtype,to_char(origintime, 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"'), to_char(modificationtime, 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"'),longitude, latitude, magnitude, depth,magnitudetype, depthtype, evaluationmethod, evaluationstatus, evaluationmode, earthmodel, usedphasecount, usedstationcount,magnitudestationcount, minimumdistance, azimuthalgap,originerror,magnitudeuncertainty) as csv from haz.quake_search_v1` params, err := getQueryParams(v) if err != nil { return weft.BadRequest(err.Error()) } sqlString, args := getSqlQuery(sqlString, params) rows, err := db.Query(sqlString, args...) if err != nil { return weft.InternalServerError(err) } defer rows.Close() var ( // b bytes.Buffer d string ) b.WriteString("publicid,eventtype,origintime,modificationtime,longitude, latitude, magnitude, depth,magnitudetype,depthtype," + "evaluationmethod,evaluationstatus,evaluationmode,earthmodel,usedphasecount,usedstationcount,magnitudestationcount,minimumdistance," + "azimuthalgap,originerror,magnitudeuncertainty") b.WriteString("\n") for rows.Next() { err := rows.Scan(&d) if err != nil { return weft.InternalServerError(err) } b.WriteString(d) b.WriteString("\n") } // send result response h.Set("Content-Disposition", `attachment; filename="earthquakes.csv"`) h.Set("Content-Type", CONTENT_TYPE_CSV) return &weft.StatusOK }
func dataSitePut(r *http.Request, h http.Header, b *bytes.Buffer) *weft.Result { v := r.URL.Query() siteID := v.Get("siteID") var err error var latitude, longitude float64 if latitude, err = strconv.ParseFloat(v.Get("latitude"), 64); err != nil { return weft.BadRequest("latitude invalid") } if longitude, err = strconv.ParseFloat(v.Get("longitude"), 64); err != nil { return weft.BadRequest("longitude invalid") } var result sql.Result // TODO - use upsert with PG 9.5? // return if insert succeeds if result, err = db.Exec(`INSERT INTO data.site(siteID, latitude, longitude) VALUES($1, $2, $3)`, siteID, latitude, longitude); err == nil { var i int64 if i, err = result.RowsAffected(); err != nil { return weft.InternalServerError(err) } if i == 1 { return &weft.StatusOK } } // return if update one row if pqErr, ok := err.(*pq.Error); ok && pqErr.Code == errorUniqueViolation { if result, err = db.Exec(`UPDATE data.site SET latitude=$2, longitude=$3 where siteID=$1`, siteID, latitude, longitude); err == nil { var i int64 if i, err = result.RowsAffected(); err != nil { return weft.InternalServerError(err) } if i == 1 { return &weft.StatusOK } } } if err == nil { err = fmt.Errorf("no rows affected, check your query.") } return weft.InternalServerError(err) }
func fieldStatePut(r *http.Request, h http.Header, b *bytes.Buffer) *weft.Result { q := r.URL.Query() deviceID := q.Get("deviceID") typeID := q.Get("typeID") var err error var value bool if value, err = strconv.ParseBool(q.Get("value")); err != nil { return weft.BadRequest("invalid value") } var t time.Time if t, err = time.Parse(time.RFC3339, q.Get("time")); err != nil { return weft.BadRequest("invalid time") } var result sql.Result if result, err = db.Exec(`UPDATE field.state SET time = $3, value = $4 WHERE devicePK = (SELECT devicePK from field.device WHERE deviceID = $1) AND typePK = (SELECT typePK from field.state_type WHERE typeID = $2)`, deviceID, typeID, t, value); err != nil { return weft.InternalServerError(err) } // If no rows change either the values are old or it's the first time we've seen this metric. var u int64 if u, err = result.RowsAffected(); err != nil { return weft.InternalServerError(err) } if u == 1 { return &weft.StatusOK } else if result, err = db.Exec(`INSERT INTO field.state(devicePK, typePK, time, value) SELECT devicePK, typePK, $3, $4 FROM field.device, field.state_type WHERE deviceID = $1 AND typeID = $2`, deviceID, typeID, t, value); err == nil { var i int64 if i, err = result.RowsAffected(); err != nil { return weft.InternalServerError(err) } if i == 1 { return &weft.StatusOK } } return weft.InternalServerError(err) }