add orderby clause
This commit is contained in:
parent
d90d7a0af4
commit
8e314e9303
10
db.go
10
db.go
|
@ -141,12 +141,20 @@ type LimitOffsetModifier struct {
|
||||||
Offset int
|
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)
|
clause := fmt.Sprintf(" LIMIT %d OFFSET %d", l.Limit, l.Offset)
|
||||||
sb.WriteString(clause)
|
sb.WriteString(clause)
|
||||||
return nil
|
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.
|
// BusEventFilter is a filter for bus events.
|
||||||
type BusEventFilter struct {
|
type BusEventFilter struct {
|
||||||
Names []string
|
Names []string
|
||||||
|
|
6
http.go
6
http.go
|
@ -264,12 +264,14 @@ func apiV1GetValues(db *TelemDb) http.HandlerFunc {
|
||||||
// override the bus event filter name option
|
// override the bus event filter name option
|
||||||
bef.Names = []string{name}
|
bef.Names = []string{name}
|
||||||
|
|
||||||
|
var order = &OrderByTimestampModifer{}
|
||||||
|
|
||||||
var res []Datum
|
var res []Datum
|
||||||
// make the call, skip the limit modifier if it's nil.
|
// make the call, skip the limit modifier if it's nil.
|
||||||
if lim == nil {
|
if lim == nil {
|
||||||
res, err = db.GetValues(r.Context(), *bef, field)
|
res, err = db.GetValues(r.Context(), *bef, field, order)
|
||||||
} else {
|
} else {
|
||||||
res, err = db.GetValues(r.Context(), *bef, field, lim)
|
res, err = db.GetValues(r.Context(), *bef, field, lim, order)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// 500 server error:
|
// 500 server error:
|
||||||
|
|
36
readme.md
36
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
|
This is handled automatically; builds will exclude the socketCAN files and
|
||||||
the additional commands and features will not be present in the CLI.
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
169
web/src/app.js
169
web/src/app.js
|
@ -8,36 +8,36 @@ openmct.install(openmct.plugins.UTCTimeSystem());
|
||||||
openmct.install(openmct.plugins.Clock({ enableClockIndicator: true }));
|
openmct.install(openmct.plugins.Clock({ enableClockIndicator: true }));
|
||||||
openmct.install(openmct.plugins.Timer());
|
openmct.install(openmct.plugins.Timer());
|
||||||
openmct.install(openmct.plugins.Timelist());
|
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.time.timeSystem('utc');
|
||||||
openmct.install(openmct.plugins.Espresso());
|
openmct.install(openmct.plugins.Espresso());
|
||||||
|
|
||||||
openmct.install(
|
openmct.install(
|
||||||
openmct.plugins.Conductor({
|
openmct.plugins.Conductor({
|
||||||
menuOptions: [
|
menuOptions: [
|
||||||
{
|
{
|
||||||
name: 'Fixed',
|
name: 'Fixed',
|
||||||
timeSystem: 'utc',
|
timeSystem: 'utc',
|
||||||
bounds: {
|
bounds: {
|
||||||
start: Date.now() - 30000000,
|
start: Date.now() - 30000000,
|
||||||
end: Date.now()
|
end: Date.now()
|
||||||
},
|
},
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Realtime',
|
name: 'Realtime',
|
||||||
timeSystem: 'utc',
|
timeSystem: 'utc',
|
||||||
clock: 'local',
|
clock: 'local',
|
||||||
clockOffsets: {
|
clockOffsets: {
|
||||||
start: -30000000,
|
start: -30000000,
|
||||||
end: 30000
|
end: 30000
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,73 +61,73 @@ function getSchema() {
|
||||||
|
|
||||||
const objectProvider = {
|
const objectProvider = {
|
||||||
get: function (id) {
|
get: function (id) {
|
||||||
return getSchema().then((schema) => {
|
return getSchema().then((schema) => {
|
||||||
if (id.key === "car") {
|
if (id.key === "car") {
|
||||||
const comp = schema.packets.map((x) => {
|
const comp = schema.packets.map((x) => {
|
||||||
return {
|
return {
|
||||||
key: x.name,
|
key: x.name,
|
||||||
namespace: "umnsvp"
|
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 {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
})
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,6 +142,7 @@ const TelemHistoryProvider = {
|
||||||
start: new Date(opt.start).toISOString(),
|
start: new Date(opt.start).toISOString(),
|
||||||
end: new Date(opt.end).toISOString(),
|
end: new Date(opt.end).toISOString(),
|
||||||
})
|
})
|
||||||
|
console.log((opt.end - opt.start)/opt.size)
|
||||||
return fetch(url + params).then((resp) => {
|
return fetch(url + params).then((resp) => {
|
||||||
return resp.json()
|
return resp.json()
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in a new issue