From 8e314e9303bda46d59ef387006f9cc5eacc50fa3 Mon Sep 17 00:00:00 2001 From: saji Date: Wed, 6 Mar 2024 10:48:40 -0600 Subject: [PATCH] add orderby clause --- db.go | 10 ++- http.go | 6 +- readme.md | 36 ++++++++++ web/src/app.js | 175 +++++++++++++++++++++++++------------------------ 4 files changed, 137 insertions(+), 90 deletions(-) diff --git a/db.go b/db.go index 039641d..f434392 100644 --- a/db.go +++ b/db.go @@ -141,12 +141,20 @@ type LimitOffsetModifier struct { Offset int } -func (l LimitOffsetModifier) ModifyStatement(sb *strings.Builder) error { +func (l *LimitOffsetModifier) ModifyStatement(sb *strings.Builder) error { clause := fmt.Sprintf(" LIMIT %d OFFSET %d", l.Limit, l.Offset) sb.WriteString(clause) return nil } +type OrderByTimestampModifer struct { +} + +func (o *OrderByTimestampModifer) ModifyStatement(sb *strings.Builder) error { + sb.WriteString(" ORDER BY ts DESC") + return nil +} + // BusEventFilter is a filter for bus events. type BusEventFilter struct { Names []string diff --git a/http.go b/http.go index 43e9b76..388a4d3 100644 --- a/http.go +++ b/http.go @@ -264,12 +264,14 @@ func apiV1GetValues(db *TelemDb) http.HandlerFunc { // override the bus event filter name option bef.Names = []string{name} + var order = &OrderByTimestampModifer{} + var res []Datum // make the call, skip the limit modifier if it's nil. if lim == nil { - res, err = db.GetValues(r.Context(), *bef, field) + res, err = db.GetValues(r.Context(), *bef, field, order) } else { - res, err = db.GetValues(r.Context(), *bef, field, lim) + res, err = db.GetValues(r.Context(), *bef, field, lim, order) } if err != nil { // 500 server error: diff --git a/readme.md b/readme.md index 0942a33..fd810d5 100644 --- a/readme.md +++ b/readme.md @@ -68,3 +68,39 @@ Certain features, like socketCAN support, are only enabled on platforms that sup This is handled automatically; builds will exclude the socketCAN files and the additional commands and features will not be present in the CLI. +### Lightweight Build + +This doesn't include the OpenMCT files, but is simpler to build, and doesn't require Node setup. +You must install Go. +``` +$ go build ./cmd/gotelem +``` + +### Full Build + +This includes an integrated OpenMCT build, which automatically connects to the Telemetry server +for historical and live data. You must have both Go and Node.JS installed. + +``` +$ cd web/ +$ npm install +$ npm run build +$ cd .. +$ go build -tags openmct ./cmd/gotelem +``` + +## Development + +During development, it can be useful to have the OpenMCT sources be served separately from Gotelem, +so you don't need to rebuild everything. This case is supported: + +``` +$ go run ./cmd/gotelem server --db gotelem.db # in one terminal +$ npm run serve # in a separate terminal +``` +When using the dev server, webpack will set the Gotelem URL to `localhost:8080`. If you're running +Gotelem using the default settings, this should work out of the box. Making changes to the OpenMCT +plugins will trigger a refresh automatically. + + + diff --git a/web/src/app.js b/web/src/app.js index bae3947..6be1494 100644 --- a/web/src/app.js +++ b/web/src/app.js @@ -8,36 +8,36 @@ openmct.install(openmct.plugins.UTCTimeSystem()); openmct.install(openmct.plugins.Clock({ enableClockIndicator: true })); openmct.install(openmct.plugins.Timer()); openmct.install(openmct.plugins.Timelist()); -openmct.time.clock('local', {start: -5 * 60 * 1000, end: 0}); +openmct.time.clock('local', { start: -5 * 60 * 1000, end: 0 }); openmct.time.timeSystem('utc'); openmct.install(openmct.plugins.Espresso()); - openmct.install( - openmct.plugins.Conductor({ - menuOptions: [ +openmct.install( + openmct.plugins.Conductor({ + menuOptions: [ { - name: 'Fixed', - timeSystem: 'utc', - bounds: { - start: Date.now() - 30000000, - end: Date.now() - }, + name: 'Fixed', + timeSystem: 'utc', + bounds: { + start: Date.now() - 30000000, + end: Date.now() + }, }, { - name: 'Realtime', - timeSystem: 'utc', - clock: 'local', - clockOffsets: { - start: -30000000, - end: 30000 - }, - - + name: 'Realtime', + timeSystem: 'utc', + clock: 'local', + clockOffsets: { + start: -30000000, + end: 30000 + }, + + } - ] - }) - ); + ] + }) +); @@ -61,73 +61,73 @@ function getSchema() { const objectProvider = { get: function (id) { - return getSchema().then((schema) => { - if (id.key === "car") { - const comp = schema.packets.map((x) => { - return { - key: x.name, - namespace: "umnsvp" - } - }) - return { - identifier: id, - name: "the solar car", - type: 'folder', - location: 'ROOT', - composition: comp - } - } - var pkt = schema.packets.find((x) => x.name === id.key) - if (pkt) { - // if the key matches one of the packet names, - // we know it's a field. - const comp = pkt.data.map((field) => { - return { - // we have to do this since - // we can't get the packet name otherwise. - key: `${pkt.name}.${field.name}`, - namespace: "umnsvp" - } - }) - return { - identifier: id, - name: pkt.name, - type: 'folder', - composition: comp - } - } - // at this point it's definitely a field aka umnsvp-datum - var [pktName, fieldName] = id.key.split('.') - return { - identifier: id, - name: fieldName, - type: 'umnsvp-datum', - telemetry: { - values: [ - { - key: "value", - source: "val", - name: "Value", - "format": "float", - hints: { - range: 1 - } - }, - { - key: "utc", - source: "ts", - name: "Timestamp", - format: "utc", - hints: { - domain: 1 - } - + return getSchema().then((schema) => { + if (id.key === "car") { + const comp = schema.packets.map((x) => { + return { + key: x.name, + namespace: "umnsvp" } - ] + }) + return { + identifier: id, + name: "the solar car", + type: 'folder', + location: 'ROOT', + composition: comp + } } - } + var pkt = schema.packets.find((x) => x.name === id.key) + if (pkt) { + // if the key matches one of the packet names, + // we know it's a field. + const comp = pkt.data.map((field) => { + return { + // we have to do this since + // we can't get the packet name otherwise. + key: `${pkt.name}.${field.name}`, + namespace: "umnsvp" + } + }) + return { + identifier: id, + name: pkt.name, + type: 'folder', + composition: comp + } + } + // at this point it's definitely a field aka umnsvp-datum + var [pktName, fieldName] = id.key.split('.') + return { + identifier: id, + name: fieldName, + type: 'umnsvp-datum', + telemetry: { + values: [ + { + key: "value", + source: "val", + name: "Value", + "format": "float", + hints: { + range: 1 + } + }, + { + key: "utc", + source: "ts", + name: "Timestamp", + format: "utc", + hints: { + domain: 1 + } - }) + } + ] + } + } + + }) } } @@ -141,7 +141,8 @@ const TelemHistoryProvider = { var params = new URLSearchParams({ start: new Date(opt.start).toISOString(), end: new Date(opt.end).toISOString(), - }) + }) + console.log((opt.end - opt.start)/opt.size) return fetch(url + params).then((resp) => { return resp.json() })