Compare commits
115 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c54945d763 | |||
| 7fc0588e4e | |||
| 0da3531d14 | |||
| ba5f87d567 | |||
| 58af1e1a61 | |||
| 793d68d3ee | |||
| a40a8c5ffd | |||
| 35f1b3f45f | |||
| 196bbfd05b | |||
| 9199977b89 | |||
| 2d2b823592 | |||
| 1398bae5b1 | |||
| b303568a0f | |||
| b0e18cb212 | |||
| 0fbc6e2758 | |||
| 435bf451a5 | |||
| 3cc6264f2a | |||
| 32bb0e7785 | |||
| 6cda14bc32 | |||
| 8e0134aa9b | |||
| 80e1fd0b2b | |||
| 4cee6c8f4a | |||
| 9e05dd1aba | |||
| 5ee814d1a2 | |||
| f45cea959d | |||
| f6ca896691 | |||
| c3246200d0 | |||
| 205c0bdec0 | |||
| 9766839118 | |||
| 8369ccc8da | |||
| fb704b32c5 | |||
| fe0ae5f827 | |||
| 55c090e42a | |||
| da5e98870f | |||
| 917632b964 | |||
| 55c9ad4f76 | |||
| 9dd271b3aa | |||
| ed60415f27 | |||
| b4a3b09fb1 | |||
| 730207c637 | |||
| 1301333629 | |||
| 9f91328c08 | |||
| 481f62fb6c | |||
| 0cdaafcc44 | |||
| 0ce9deeb2e | |||
| f5e3efa635 | |||
| 4bb37ab4ff | |||
| 36f2e35231 | |||
| 0c8cc110ab | |||
| ecd0b8ecf5 | |||
| 3547f0e377 | |||
| 76f788c685 | |||
| 8c7812e737 | |||
| 2cb1f0daa4 | |||
| c2a3fe5732 | |||
| 536bf387c8 | |||
| 1632419420 | |||
| fd3f440ab5 | |||
| 26fe6469a5 | |||
| 3ec0f58975 | |||
| dd7107b1a9 | |||
| 6f6da95780 | |||
| 2e6a9b9281 | |||
| ec11f2541d | |||
| e74f0fd895 | |||
| 863f919471 | |||
| f5a6ec00b2 | |||
| 9171452057 | |||
| e611b21d80 | |||
| 4c3b640a54 | |||
| e4dda5b308 | |||
| 4a21d4edfa | |||
| c3f9240801 | |||
| a7f6e2b9a1 | |||
| e66f631c2f | |||
| f07d27b325 | |||
| b1dcc863e5 | |||
| acee3f9465 | |||
| 7805e89f5f | |||
| c7698fa06e | |||
| ca73b7c14e | |||
| 6ded3ec741 | |||
| 06790ba8c8 | |||
| b45f27f831 | |||
| bc5fb7b6d7 | |||
| 8c18b2d3f5 | |||
| 39efd32509 | |||
| 954301f57d | |||
| e0ebf17cab | |||
| c7140d8394 | |||
| 53351c7349 | |||
| bc2976c0db | |||
| 2a9bb7f888 | |||
| c0ae64b035 | |||
| 292d93622f | |||
| c59d482333 | |||
| 5fb76a76ca | |||
| 1bde599b46 | |||
| fffda650bb | |||
| a64aa0db7c | |||
| 8a26d8bf61 | |||
| f42e2d29b0 | |||
| 104fcb8066 | |||
| b0b0b487dc | |||
| 4d6b607070 | |||
| ed0b0443c6 | |||
| c8d3fa58ab | |||
| 798367bb5e | |||
| 2aafb0024d | |||
| d7b849d94b | |||
| 100787f047 | |||
| 6003b19d2c | |||
| a4cd8d88d9 | |||
| fa1256b3c9 | |||
| 379d174f2b |
1
.gitignore
vendored
1
.gitignore
vendored
@ -162,3 +162,4 @@ Temporary Items
|
||||
gpsconfig.yml
|
||||
config.yml
|
||||
_db
|
||||
/build
|
||||
|
||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "static/indicators"]
|
||||
path = static/indicators
|
||||
url = https://github.com/sebmatton/jQuery-Flight-Indicators.git
|
||||
4
.idea/jsLibraryMappings.xml
generated
4
.idea/jsLibraryMappings.xml
generated
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="JavaScriptLibraryMappings">
|
||||
<file url="PROJECT" libraries="{Chart, Chart.js}" />
|
||||
<file url="PROJECT" libraries="{Chart, Chart.js, mapbox-gl, three.js}" />
|
||||
</component>
|
||||
</project>
|
||||
</project>
|
||||
|
||||
1
.idea/vcs.xml
generated
1
.idea/vcs.xml
generated
@ -2,5 +2,6 @@
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/static/indicators" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
BIN
backups/_db-201218-01/raw/000000.vlog
Normal file
BIN
backups/_db-201218-01/raw/000000.vlog
Normal file
Binary file not shown.
1
backups/_db-201218-01/raw/KEYREGISTRY
Normal file
1
backups/_db-201218-01/raw/KEYREGISTRY
Normal file
@ -0,0 +1 @@
|
||||
ˆ‰œœ+¥¶Îz {Hello Badger
|
||||
1
backups/_db-201218-01/raw/LOCK
Normal file
1
backups/_db-201218-01/raw/LOCK
Normal file
@ -0,0 +1 @@
|
||||
38895
|
||||
BIN
backups/_db-201218-01/raw/MANIFEST
Normal file
BIN
backups/_db-201218-01/raw/MANIFEST
Normal file
Binary file not shown.
BIN
backups/_db-201218-01/records/000000.vlog
Normal file
BIN
backups/_db-201218-01/records/000000.vlog
Normal file
Binary file not shown.
1
backups/_db-201218-01/records/KEYREGISTRY
Normal file
1
backups/_db-201218-01/records/KEYREGISTRY
Normal file
@ -0,0 +1 @@
|
||||
;µÐÕ0.Ñþý|uG…Hello Badger
|
||||
1
backups/_db-201218-01/records/LOCK
Normal file
1
backups/_db-201218-01/records/LOCK
Normal file
@ -0,0 +1 @@
|
||||
38895
|
||||
BIN
backups/_db-201218-01/records/MANIFEST
Normal file
BIN
backups/_db-201218-01/records/MANIFEST
Normal file
Binary file not shown.
BIN
backups/_db-201218-01/sensor/000000.vlog
Normal file
BIN
backups/_db-201218-01/sensor/000000.vlog
Normal file
Binary file not shown.
1
backups/_db-201218-01/sensor/KEYREGISTRY
Normal file
1
backups/_db-201218-01/sensor/KEYREGISTRY
Normal file
@ -0,0 +1 @@
|
||||
枯華虌𤥢崱v叐<76>Hello Badger
|
||||
1
backups/_db-201218-01/sensor/LOCK
Normal file
1
backups/_db-201218-01/sensor/LOCK
Normal file
@ -0,0 +1 @@
|
||||
27554
|
||||
BIN
backups/_db-201218-01/sensor/MANIFEST
Normal file
BIN
backups/_db-201218-01/sensor/MANIFEST
Normal file
Binary file not shown.
BIN
backups/_db-201218-01/trackings/000000.vlog
Normal file
BIN
backups/_db-201218-01/trackings/000000.vlog
Normal file
Binary file not shown.
1
backups/_db-201218-01/trackings/KEYREGISTRY
Normal file
1
backups/_db-201218-01/trackings/KEYREGISTRY
Normal file
@ -0,0 +1 @@
|
||||
ßÁuðÓJäe»|?^<5E>¢˜Hello Badger
|
||||
1
backups/_db-201218-01/trackings/LOCK
Normal file
1
backups/_db-201218-01/trackings/LOCK
Normal file
@ -0,0 +1 @@
|
||||
38895
|
||||
BIN
backups/_db-201218-01/trackings/MANIFEST
Normal file
BIN
backups/_db-201218-01/trackings/MANIFEST
Normal file
Binary file not shown.
BIN
backups/_db-210115-01/raw/000000.vlog
Normal file
BIN
backups/_db-210115-01/raw/000000.vlog
Normal file
Binary file not shown.
1
backups/_db-210115-01/raw/KEYREGISTRY
Normal file
1
backups/_db-210115-01/raw/KEYREGISTRY
Normal file
@ -0,0 +1 @@
|
||||
ˆ‰œœ+¥¶Îz {Hello Badger
|
||||
1
backups/_db-210115-01/raw/LOCK
Normal file
1
backups/_db-210115-01/raw/LOCK
Normal file
@ -0,0 +1 @@
|
||||
38895
|
||||
BIN
backups/_db-210115-01/raw/MANIFEST
Normal file
BIN
backups/_db-210115-01/raw/MANIFEST
Normal file
Binary file not shown.
BIN
backups/_db-210115-01/records/000000.vlog
Normal file
BIN
backups/_db-210115-01/records/000000.vlog
Normal file
Binary file not shown.
1
backups/_db-210115-01/records/KEYREGISTRY
Normal file
1
backups/_db-210115-01/records/KEYREGISTRY
Normal file
@ -0,0 +1 @@
|
||||
;µÐÕ0.Ñþý|uG…Hello Badger
|
||||
1
backups/_db-210115-01/records/LOCK
Normal file
1
backups/_db-210115-01/records/LOCK
Normal file
@ -0,0 +1 @@
|
||||
38895
|
||||
BIN
backups/_db-210115-01/records/MANIFEST
Normal file
BIN
backups/_db-210115-01/records/MANIFEST
Normal file
Binary file not shown.
BIN
backups/_db-210115-01/sensor/000000.vlog
Normal file
BIN
backups/_db-210115-01/sensor/000000.vlog
Normal file
Binary file not shown.
1
backups/_db-210115-01/sensor/KEYREGISTRY
Normal file
1
backups/_db-210115-01/sensor/KEYREGISTRY
Normal file
@ -0,0 +1 @@
|
||||
枯華虌𤥢崱v叐<76>Hello Badger
|
||||
1
backups/_db-210115-01/sensor/LOCK
Normal file
1
backups/_db-210115-01/sensor/LOCK
Normal file
@ -0,0 +1 @@
|
||||
6958
|
||||
BIN
backups/_db-210115-01/sensor/MANIFEST
Normal file
BIN
backups/_db-210115-01/sensor/MANIFEST
Normal file
Binary file not shown.
BIN
backups/_db-210115-01/trackings/000000.vlog
Normal file
BIN
backups/_db-210115-01/trackings/000000.vlog
Normal file
Binary file not shown.
1
backups/_db-210115-01/trackings/KEYREGISTRY
Normal file
1
backups/_db-210115-01/trackings/KEYREGISTRY
Normal file
@ -0,0 +1 @@
|
||||
ßÁuðÓJäe»|?^<5E>¢˜Hello Badger
|
||||
1
backups/_db-210115-01/trackings/LOCK
Normal file
1
backups/_db-210115-01/trackings/LOCK
Normal file
@ -0,0 +1 @@
|
||||
6958
|
||||
BIN
backups/_db-210115-01/trackings/MANIFEST
Normal file
BIN
backups/_db-210115-01/trackings/MANIFEST
Normal file
Binary file not shown.
@ -1,53 +1,42 @@
|
||||
/**
|
||||
only for testing purposes
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"git.timovolkmann.de/gyrogpsc/core"
|
||||
"git.timovolkmann.de/gyrogpsc/storage"
|
||||
"git.timovolkmann.de/gyrogpsc/web"
|
||||
"github.com/google/uuid"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/viper"
|
||||
"net/http"
|
||||
_ "net/http/pprof"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
//f, err := os.Create("_profile.pprof")
|
||||
//if err != nil {
|
||||
// logrus.Fatal(err)
|
||||
//}
|
||||
//pprof.StartCPUProfile(f)
|
||||
go func() {
|
||||
logrus.Println(http.ListenAndServe("localhost:6060", nil))
|
||||
}()
|
||||
//defer pprof.StopCPUProfile()
|
||||
|
||||
conf := configurationFromFile()
|
||||
|
||||
logrus.Debug(conf)
|
||||
|
||||
repo := storage.NewRepository(conf)
|
||||
disp := core.NewDispatcher()
|
||||
|
||||
service := core.TrackingService(repo, disp, conf)
|
||||
service := core.NewTrackingService(conf, repo, disp)
|
||||
|
||||
go func() {
|
||||
service.StartPipeline(core.TCP, core.SERIAL)
|
||||
time.Sleep(5 * time.Second)
|
||||
service.StartRecord()
|
||||
time.Sleep(10 * time.Second)
|
||||
service.StopRecord()
|
||||
time.Sleep(5 * time.Second)
|
||||
service.StartPipeline(core.TCP, core.SERIAL)
|
||||
time.Sleep(5 * time.Second)
|
||||
service.StartRecord()
|
||||
time.Sleep(60 * time.Second)
|
||||
service.StopRecord()
|
||||
time.Sleep(2 * time.Second)
|
||||
service.StopAll()
|
||||
time.Sleep(1 * time.Second)
|
||||
// Long Run
|
||||
//service.LoadTracking(uuid.MustParse("06b05aa3-6a13-4ffb-8ac7-cd35dfc0f949"))
|
||||
// Tunnel
|
||||
service.LoadTracking(uuid.MustParse("c3dbee7c-512a-4cc8-9804-21f0f2cf3c22"), true)
|
||||
|
||||
//pprof.StopCPUProfile()
|
||||
os.Exit(0)
|
||||
//os.Exit(0)
|
||||
}()
|
||||
|
||||
web.CreateServer(service, disp, conf)
|
||||
@ -5,47 +5,26 @@ import (
|
||||
"git.timovolkmann.de/gyrogpsc/storage"
|
||||
"git.timovolkmann.de/gyrogpsc/web"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/viper"
|
||||
"net/http"
|
||||
_ "net/http/pprof"
|
||||
)
|
||||
|
||||
func main() {
|
||||
conf := configurationFromFile()
|
||||
|
||||
logrus.Debug(conf)
|
||||
// launch profiling server in goroutine to debug performance issues
|
||||
go func() {
|
||||
logrus.Println(http.ListenAndServe("localhost:6060", nil))
|
||||
}()
|
||||
|
||||
// load configuration from file
|
||||
conf := core.ConfigurationFromFile()
|
||||
// initialize persistence layer
|
||||
repo := storage.NewRepository(conf)
|
||||
// initialize message distribution layer
|
||||
disp := core.NewDispatcher()
|
||||
|
||||
service := core.TrackingService(conf, repo, disp)
|
||||
// initialize core logic service and inject
|
||||
service := core.NewTrackingService(conf, repo, disp)
|
||||
|
||||
// launch webserver
|
||||
web.CreateServer(service, disp, conf)
|
||||
}
|
||||
|
||||
func configurationFromFile() *core.Configuration {
|
||||
viper.SetDefault("collectors.porttcp", ":3010")
|
||||
viper.SetDefault("collectors.portserial", "/dev/tty.usbmodem14201")
|
||||
viper.SetDefault("webserver.port", ":3011")
|
||||
viper.SetDefault("pipeline.publishIntervalMs", 50)
|
||||
viper.SetDefault("pipeline.syncUpdateIntervalMs", 494)
|
||||
viper.SetDefault("debuglevel", "INFO")
|
||||
|
||||
viper.SetConfigName("gpsconfig") // name of config file (without extension)
|
||||
viper.SetConfigType("yaml")
|
||||
viper.AddConfigPath(".")
|
||||
viper.AddConfigPath("./../../")
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
logrus.Warn("couldn't find config file. using standard configuration")
|
||||
}
|
||||
|
||||
c := core.Configuration{}
|
||||
if err := viper.Unmarshal(&c); err != nil {
|
||||
logrus.Debug("couldn't load config...")
|
||||
logrus.Error(err)
|
||||
}
|
||||
lvl, err := logrus.ParseLevel(c.Debuglevel)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
logrus.SetLevel(lvl)
|
||||
return &c
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"git.timovolkmann.de/gyrogpsc/ublox"
|
||||
"github.com/sirupsen/logrus"
|
||||
@ -70,7 +69,7 @@ func (s *serialCollector) Collect() {
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
logrus.Errorln(err)
|
||||
}
|
||||
//}
|
||||
}
|
||||
@ -212,25 +211,25 @@ func (t *tcpCollector) connectionHandler(conn net.Conn) {
|
||||
conn.Close()
|
||||
}()
|
||||
|
||||
sc := bufio.NewScanner(conn)
|
||||
maxSkip := 0
|
||||
loop:
|
||||
for sc.Scan() {
|
||||
buf := make([]byte, 2048)
|
||||
skipped := 0
|
||||
//loop:
|
||||
for {
|
||||
// Read the incoming connection into the buffer.
|
||||
res := append([]byte{}, sc.Bytes()...)
|
||||
if err2 := sc.Err(); err2 != nil {
|
||||
logrus.Warn("lost tcp link:", err2)
|
||||
n, err := conn.Read(buf)
|
||||
if err != nil {
|
||||
fmt.Println("TCP error - reading from connection:", n, err.Error())
|
||||
break
|
||||
}
|
||||
select {
|
||||
case t.out <- res:
|
||||
maxSkip = 0
|
||||
case t.out <- buf:
|
||||
skipped = 0
|
||||
default:
|
||||
logrus.Traceln("skip collecting tcp messages")
|
||||
if maxSkip >= 10 {
|
||||
break loop
|
||||
}
|
||||
maxSkip++
|
||||
//if skipped >= 10 {
|
||||
// break loop
|
||||
//}
|
||||
skipped++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,11 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// This struct represents and holds all configurable parameters
|
||||
type Configuration struct {
|
||||
Collectors struct {
|
||||
TcpCollectorPort string `mapstructure:"porttcp"`
|
||||
@ -14,3 +20,33 @@ type Configuration struct {
|
||||
} `mapstructure:"pipeline"`
|
||||
Debuglevel string `mapstructure:"debuglevel"`
|
||||
}
|
||||
|
||||
// Call this function to load configuration from gpsconfig.yml
|
||||
func ConfigurationFromFile() *Configuration {
|
||||
viper.SetDefault("collectors.porttcp", ":3010")
|
||||
viper.SetDefault("collectors.portserial", "/dev/tty.usbmodem14201")
|
||||
viper.SetDefault("webserver.port", ":3011")
|
||||
viper.SetDefault("pipeline.publishIntervalMs", 50)
|
||||
viper.SetDefault("pipeline.syncUpdateIntervalMs", 494)
|
||||
viper.SetDefault("debuglevel", "INFO")
|
||||
|
||||
viper.SetConfigName("gpsconfig") // name of config file (without extension)
|
||||
viper.SetConfigType("yaml")
|
||||
viper.AddConfigPath(".")
|
||||
viper.AddConfigPath("./../../")
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
logrus.Warn("couldn't find config file. using standard configuration")
|
||||
}
|
||||
|
||||
c := Configuration{}
|
||||
if err := viper.Unmarshal(&c); err != nil {
|
||||
logrus.Debug("couldn't load config...")
|
||||
logrus.Error(err)
|
||||
}
|
||||
lvl, err := logrus.ParseLevel(c.Debuglevel)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
logrus.SetLevel(lvl)
|
||||
return &c
|
||||
}
|
||||
|
||||
@ -10,16 +10,18 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// holds all sensor data and metadata for a specific recording
|
||||
type Tracking struct {
|
||||
TrackingMetadata
|
||||
Data []SensorData
|
||||
}
|
||||
|
||||
// holds all metadata for a specific recording
|
||||
type TrackingMetadata struct {
|
||||
UUID uuid.UUID
|
||||
TimeCreated time.Time
|
||||
Collectors []CollectorType
|
||||
Size int
|
||||
Size int
|
||||
}
|
||||
|
||||
func newTracking() Tracking {
|
||||
@ -27,7 +29,7 @@ func newTracking() Tracking {
|
||||
TrackingMetadata: TrackingMetadata{
|
||||
UUID: uuid.New(),
|
||||
},
|
||||
Data: []SensorData{},
|
||||
Data: []SensorData{},
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,7 +40,7 @@ func (s *Tracking) isEmpty() bool {
|
||||
return len(s.Data) == 0
|
||||
}
|
||||
|
||||
|
||||
// enumerate sources
|
||||
type SourceId string
|
||||
|
||||
const (
|
||||
@ -46,8 +48,7 @@ const (
|
||||
SOURCE_SERIAL SourceId = "SOURCE_SERIAL"
|
||||
)
|
||||
|
||||
var timeex int64
|
||||
|
||||
// internal unified representation for smartphone and ublox sensor data
|
||||
type SensorData struct {
|
||||
//MsgClass string
|
||||
//FixType string
|
||||
@ -56,14 +57,16 @@ type SensorData struct {
|
||||
latency int
|
||||
Servertime time.Time
|
||||
Timestamp time.Time
|
||||
Position [3]float64 `json:",omitempty"`
|
||||
PosAcc [2]float64 `json:",omitempty"`//[H,V]
|
||||
Orientation [3]float64 `json:",omitempty"`
|
||||
Speed float64 `json:",omitempty"`
|
||||
PosHeading float64 `json:",omitempty"` // Course / Heading of Motion
|
||||
HeadingAcc float64 `json:",omitempty"`
|
||||
Gyroscope [3]float64 `json:",omitempty"`
|
||||
LinearAcc [3]float64 `json:",omitempty"`
|
||||
Position [3]float64 //`json:",omitempty"`
|
||||
HAcc float64 //`json:",omitempty"`//[H,V]
|
||||
VAcc float64 //`json:",omitempty"`//[H,V]
|
||||
Orientation [3]float64 //`json:",omitempty"`
|
||||
Speed float64 //`json:",omitempty"`
|
||||
HeadDevice float64 //`json:",omitempty"` // Course / Heading of Motion
|
||||
HeadMotion float64 //`json:",omitempty"` // Course / Heading of Motion
|
||||
HeadingAcc float64 //`json:",omitempty"`
|
||||
Gyroscope [3]float64 //`json:",omitempty"`
|
||||
LinearAcc [3]float64 //`json:",omitempty"`
|
||||
|
||||
}
|
||||
|
||||
@ -128,6 +131,9 @@ var (
|
||||
errRawMessage = errors.New("raw message")
|
||||
)
|
||||
|
||||
var lastTimeOffsetIphone int64
|
||||
var lastTimeOffsetUblox int64
|
||||
|
||||
func ConvertUbxSensorData(msg interface{}) (*SensorData, error) {
|
||||
sd := &SensorData{
|
||||
//Servertime: time.Now().UTC(),
|
||||
@ -141,6 +147,12 @@ func ConvertUbxSensorData(msg interface{}) (*SensorData, error) {
|
||||
sd.Position[0] = float64(v.Lat_dege7) / 1e+7
|
||||
sd.Position[1] = float64(v.Lon_dege7) / 1e+7
|
||||
sd.Position[2] = float64(v.HMSL_mm) / 1e+3 // mm in m
|
||||
sd.HAcc = float64(v.HAcc_mm) / 1000
|
||||
sd.VAcc = float64(v.VAcc_mm) / 1000
|
||||
sd.HeadMotion = float64(v.HeadMot_dege5) / 1e+5
|
||||
sd.HeadDevice = float64(v.HeadVeh_dege5) / 1e+5
|
||||
sd.HeadingAcc = float64(v.HeadAcc_dege5) / 1e+5
|
||||
sd.Speed = float64(v.GSpeed_mm_s) * 1e-3
|
||||
case *ublox.HnrPvt:
|
||||
//logrus.Println("HNR-PVT")
|
||||
sd.itow = v.ITOW_ms
|
||||
@ -148,6 +160,12 @@ func ConvertUbxSensorData(msg interface{}) (*SensorData, error) {
|
||||
sd.Position[0] = float64(v.Lat_dege7) / 1e+7
|
||||
sd.Position[1] = float64(v.Lon_dege7) / 1e+7
|
||||
sd.Position[2] = float64(v.HMSL_mm) / 1e+3 // mm in m
|
||||
sd.HAcc = float64(v.HAcc) / 1000
|
||||
sd.VAcc = float64(v.VAcc) / 1000
|
||||
sd.HeadMotion = float64(v.HeadMot_dege5) / 1e+5
|
||||
sd.HeadDevice = float64(v.HeadVeh_dege5) / 1e+5
|
||||
sd.HeadingAcc = float64(v.HeadAcc_dege5) / 1e+5
|
||||
sd.Speed = float64(v.GSpeed_mm_s) * 1e-3 // mm in m/s
|
||||
case *ublox.NavAtt:
|
||||
//logrus.Println("NAV-ATT")
|
||||
sd.itow = v.ITOW_ms
|
||||
@ -155,13 +173,17 @@ func ConvertUbxSensorData(msg interface{}) (*SensorData, error) {
|
||||
sd.Orientation[1] = float64(v.Roll_deg) * 1e-5
|
||||
sd.Orientation[2] = float64(v.Heading_deg) * 1e-5
|
||||
case *ublox.RawMessage:
|
||||
//class := make([]byte, 2)
|
||||
//binary.LittleEndian.PutUint16(class, v.ClassID())
|
||||
//logrus.Printf("%#v, %#v", class[0],class[1])
|
||||
return nil, nil
|
||||
default:
|
||||
return nil, errNotImplemented
|
||||
}
|
||||
|
||||
if !sd.Timestamp.IsZero() && sd.Timestamp.Nanosecond() != 0 {
|
||||
lastTimeOffsetUblox = time.Now().UnixNano() - sd.Timestamp.UnixNano()
|
||||
} else {
|
||||
sd.Timestamp = time.Now().UTC().Add(time.Duration(lastTimeOffsetUblox))
|
||||
}
|
||||
|
||||
return sd, nil
|
||||
}
|
||||
|
||||
@ -180,12 +202,19 @@ func convertIPhoneSensorLog(jsonData []byte) (*SensorData, error) {
|
||||
pitch := gjson.Get(string(jsonData), "motionPitch").Float() * 180 / math.Pi
|
||||
roll := gjson.Get(string(jsonData), "motionRoll").Float() * 180 / math.Pi
|
||||
yaw := gjson.Get(string(jsonData), "motionYaw").Float() * 180 / math.Pi
|
||||
hAcc := gjson.Get(string(jsonData), "locationHorizontalAccuracy").Float()
|
||||
vAcc := gjson.Get(string(jsonData), "locationVerticalAccuracy").Float()
|
||||
headingAcc := gjson.Get(string(jsonData), "locationHeadingAccuracy").Float()
|
||||
headMotion := gjson.Get(string(jsonData), "locationCourse").Float()
|
||||
headDevice := gjson.Get(string(jsonData), "locationTrueHeading").Float()
|
||||
speed := gjson.Get(string(jsonData), "locationSpeed").Float()
|
||||
|
||||
var ts time.Time
|
||||
if timestamp != 0 {
|
||||
ts = time.Unix(0, int64(timestamp*float64(time.Second))).UTC()
|
||||
timeex = time.Now().UnixNano() - ts.UnixNano()
|
||||
} else if timeex != 0 {
|
||||
ts = time.Now().Add(time.Duration(timeex)).UTC()
|
||||
lastTimeOffsetIphone = time.Now().UnixNano() - ts.UnixNano()
|
||||
} else {
|
||||
ts = time.Now().UTC().Add(time.Duration(lastTimeOffsetIphone))
|
||||
}
|
||||
//if ts == time.Date()
|
||||
sd := &SensorData{
|
||||
@ -194,6 +223,12 @@ func convertIPhoneSensorLog(jsonData []byte) (*SensorData, error) {
|
||||
Timestamp: ts,
|
||||
Position: [3]float64{lat, lon, alt},
|
||||
Orientation: [3]float64{pitch, roll, yaw},
|
||||
HAcc: hAcc,
|
||||
VAcc: vAcc,
|
||||
HeadingAcc: headingAcc,
|
||||
HeadMotion: headMotion,
|
||||
HeadDevice: headDevice,
|
||||
Speed: speed,
|
||||
}
|
||||
if (*sd == SensorData{}) {
|
||||
return nil, errors.New("iphone sensorlog: convert empty")
|
||||
@ -209,6 +244,13 @@ func convertAndroidHyperImu(jsonData []byte) (*SensorData, error) {
|
||||
pitch := gjson.Get(string(jsonData), "orientation.0").Float()
|
||||
roll := gjson.Get(string(jsonData), "orientation.1").Float()
|
||||
yaw := gjson.Get(string(jsonData), "orientation.2").Float()
|
||||
// following properties not available for HyperIMU
|
||||
//hAcc := gjson.Get(string(jsonData), "locationHorizontalAccuracy").Float()
|
||||
//vAcc := gjson.Get(string(jsonData), "locationVerticalAccuracy").Float()
|
||||
//headingAcc := gjson.Get(string(jsonData), "locationHeadingAccuracy").Float()
|
||||
//headMotion := gjson.Get(string(jsonData), "locationCourse").Float()
|
||||
//headDevice := gjson.Get(string(jsonData), "locationTrueHeading").Float()
|
||||
//speed := gjson.Get(string(jsonData), "locationSpeed").Float()
|
||||
|
||||
sd := &SensorData{
|
||||
//Servertime: time.Now().UTC(),
|
||||
|
||||
@ -6,12 +6,14 @@ import (
|
||||
"golang.org/x/sync/semaphore"
|
||||
)
|
||||
|
||||
// dispatcher is responsible to distribute messages to subscribed listeners
|
||||
type dispatcher struct {
|
||||
listeners map[int16]chan string
|
||||
counter int16
|
||||
sem *semaphore.Weighted
|
||||
}
|
||||
|
||||
// Returns initialized dispatcher.
|
||||
func NewDispatcher() *dispatcher {
|
||||
return &dispatcher{
|
||||
listeners: make(map[int16]chan string),
|
||||
@ -20,19 +22,20 @@ func NewDispatcher() *dispatcher {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// disable or enable streaming without removing all listeners from dispatcher
|
||||
func (d *dispatcher) SetStreaming(s bool) bool {
|
||||
if ok := d.sem.TryAcquire(1); s && ok {
|
||||
// if i want to turn on and can get semaphore then return success
|
||||
// if you want to turn on and can get semaphore then return success
|
||||
return true
|
||||
} else if !s && !ok {
|
||||
// if i want to turn off and cant get semaphore, i can safely turn off by releasing semaphore and return success
|
||||
// if you want to turn off and cant get semaphore, you can safely turn off by releasing semaphore and return success
|
||||
d.sem.Release(1)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// if closed, dispatcher will not forward published messages and drops them.
|
||||
func (d *dispatcher) IsClosed() bool {
|
||||
if d.sem.TryAcquire(1) {
|
||||
d.sem.Release(1)
|
||||
@ -41,16 +44,23 @@ func (d *dispatcher) IsClosed() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
// publishes message to all subscribed listeners.
|
||||
// if dispatcher closed, dispatcher will not forward published messages and drops them.
|
||||
func (d *dispatcher) Publish(message string) {
|
||||
if d.IsClosed() { return }
|
||||
if d.IsClosed() {
|
||||
return
|
||||
}
|
||||
logrus.Tracef("publishing to %v listeners\n", len(d.listeners))
|
||||
logrus.Trace(message)
|
||||
for _, ch := range d.listeners {
|
||||
ch <- message
|
||||
select {
|
||||
case ch <- message:
|
||||
default:
|
||||
logrus.Traceln("dispatcher: skip closed channel")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Registers new client as listener and returns his id and a channel which is used to receive all messages.
|
||||
func (d *dispatcher) Subscribe() (id int16, receiver <-chan string) {
|
||||
key := d.counter
|
||||
d.counter++
|
||||
@ -59,6 +69,8 @@ func (d *dispatcher) Subscribe() (id int16, receiver <-chan string) {
|
||||
return key, rec
|
||||
}
|
||||
|
||||
// Unsubscribes Listener with given ID.
|
||||
// if listener with given ID exists, it will be deleted and no error will be returned.
|
||||
func (d *dispatcher) Unsubscribe(id int16) error {
|
||||
receiver, ok := d.listeners[id]
|
||||
if !ok {
|
||||
|
||||
@ -2,25 +2,25 @@ package core
|
||||
|
||||
import "github.com/google/uuid"
|
||||
|
||||
// abstraction for dispatcher to make it replaceable
|
||||
type Subscriber interface {
|
||||
Subscribe() (int16, <-chan string)
|
||||
Unsubscribe(id int16) error
|
||||
}
|
||||
|
||||
// abstraction for dispatcher to make it replaceable
|
||||
type Publisher interface {
|
||||
Publish(message string)
|
||||
Streamer
|
||||
}
|
||||
|
||||
type Processor interface {
|
||||
Push(data *SensorData) error
|
||||
}
|
||||
|
||||
// implementing struct should be responsible for message forwarding (to client)
|
||||
type Streamer interface {
|
||||
SetStreaming(s bool) (ok bool)
|
||||
IsClosed() bool
|
||||
}
|
||||
|
||||
// abstraction for persistance layer
|
||||
type Storer interface {
|
||||
Save(tracking Tracking) error
|
||||
LoadAll() ([]TrackingMetadata, error)
|
||||
|
||||
239
core/pipeline.go
239
core/pipeline.go
@ -1,239 +0,0 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/sync/semaphore"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type pipeline struct {
|
||||
active bool
|
||||
record bool
|
||||
synchroniz synchronizer
|
||||
buffer pipeBuffer
|
||||
publisher Publisher
|
||||
storer Tracker
|
||||
publishTicker *time.Ticker
|
||||
mu sync.RWMutex
|
||||
sema *semaphore.Weighted
|
||||
}
|
||||
|
||||
// pipeline implements Runner & Processor
|
||||
func NewPipeline(d Publisher, s Tracker, conf *Configuration) *pipeline {
|
||||
return &pipeline{
|
||||
false,
|
||||
false,
|
||||
synchronizer{
|
||||
//bufferSize: 100,
|
||||
mutex: &sync.RWMutex{},
|
||||
updateTicker: time.NewTicker(time.Duration(conf.Pipeline.SyncUpdateIntervalMs) * time.Millisecond),
|
||||
},
|
||||
pipeBuffer{
|
||||
tcpMutex: &sync.Mutex{},
|
||||
serialMutex: &sync.Mutex{},
|
||||
},
|
||||
d,
|
||||
s,
|
||||
time.NewTicker(time.Duration(conf.Pipeline.PublishIntervalMs) * time.Millisecond),
|
||||
sync.RWMutex{},
|
||||
semaphore.NewWeighted(2),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *pipeline) isPipeActive() bool {
|
||||
p.mu.RLock()
|
||||
defer p.mu.RUnlock()
|
||||
return p.active
|
||||
}
|
||||
func (p *pipeline) isPipeRecording() bool {
|
||||
p.mu.RLock()
|
||||
defer p.mu.RUnlock()
|
||||
return p.record
|
||||
}
|
||||
|
||||
func (p *pipeline) Run() {
|
||||
p.sema.Acquire(context.Background(), 1) // !!! n=2 wenn synchronizer mitläuft
|
||||
p.mu.Lock()
|
||||
p.active = true
|
||||
p.mu.Unlock()
|
||||
logrus.Println("pipeline: processing service started")
|
||||
//go func() {
|
||||
// for p.isPipeActive() {
|
||||
// <-p.synchroniz.updateTicker.C
|
||||
// err := p.refreshDelay()
|
||||
// if err != nil {
|
||||
// logrus.Debugln(err)
|
||||
// }
|
||||
// }
|
||||
// p.sema.Release(1)
|
||||
// logrus.Println("pipeline: updater stopped")
|
||||
//}()
|
||||
go func() {
|
||||
for p.isPipeActive() {
|
||||
<-p.publishTicker.C
|
||||
err := p.publish()
|
||||
if err != nil && err.Error() != "no data available" {
|
||||
logrus.Trace(err)
|
||||
}
|
||||
}
|
||||
p.sema.Release(1)
|
||||
logrus.Println("pipeline: publisher stopped")
|
||||
}()
|
||||
}
|
||||
|
||||
func (p *pipeline) Record() {
|
||||
p.record = true
|
||||
}
|
||||
func (p *pipeline) StopRecord() {
|
||||
p.record = false
|
||||
}
|
||||
|
||||
func (p *pipeline) Push(data *SensorData) error {
|
||||
if (data == nil || *data == SensorData{}) {
|
||||
return errors.New("no data")
|
||||
}
|
||||
//logrus.Println("push data to pipeline:", string(data.source))
|
||||
switch data.source {
|
||||
case SOURCE_TCP:
|
||||
go p.pushTcpDataToBuffer(*data)
|
||||
case SOURCE_SERIAL:
|
||||
go p.pushSerialDataToBuffer(*data)
|
||||
default:
|
||||
panic("pipeline: invalid data source")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *pipeline) publish() error {
|
||||
p.buffer.serialMutex.Lock()
|
||||
p.buffer.tcpMutex.Lock()
|
||||
|
||||
if (p.buffer.MeasTcp == SensorData{} && p.buffer.MeasSerial == SensorData{}) {
|
||||
p.buffer.tcpMutex.Unlock()
|
||||
p.buffer.serialMutex.Unlock()
|
||||
return errors.New("no data available")
|
||||
}
|
||||
if cmp.Equal(p.buffer.MeasTcp, p.buffer.LastMeasTcp, cmpopts.IgnoreUnexported(SensorData{})) &&
|
||||
cmp.Equal(p.buffer.MeasSerial, p.buffer.LastMeasSerial, cmpopts.IgnoreUnexported(SensorData{})) {
|
||||
p.buffer.tcpMutex.Unlock()
|
||||
p.buffer.serialMutex.Unlock()
|
||||
return errors.New("same data")
|
||||
}
|
||||
logrus.Debugf("–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––")
|
||||
logrus.Tracef("SER old: %-40s %-40s %v %v", p.buffer.LastMeasSerial.Timestamp.Format(time.RFC3339Nano), p.buffer.LastMeasSerial.Servertime.Format(time.RFC3339Nano), p.buffer.LastMeasSerial.Position, p.buffer.LastMeasSerial.Orientation)
|
||||
logrus.Debugf("SER new: %-40s %-40s %v %v", p.buffer.MeasSerial.Timestamp.Format(time.RFC3339Nano), p.buffer.MeasSerial.Servertime.Format(time.RFC3339Nano), p.buffer.MeasSerial.Position, p.buffer.MeasSerial.Orientation)
|
||||
logrus.Tracef("TCP old: %-40s %-40s %v %v", p.buffer.LastMeasTcp.Timestamp.Format(time.RFC3339Nano), p.buffer.LastMeasTcp.Servertime.Format(time.RFC3339Nano), p.buffer.LastMeasTcp.Position, p.buffer.LastMeasTcp.Orientation)
|
||||
logrus.Debugf("TCP new: %-40s %-40s %v %v", p.buffer.MeasTcp.Timestamp.Format(time.RFC3339Nano), p.buffer.MeasTcp.Servertime.Format(time.RFC3339Nano), p.buffer.MeasTcp.Position, p.buffer.MeasTcp.Orientation)
|
||||
p.buffer.LastMeasTcp = p.buffer.MeasTcp
|
||||
p.buffer.LastMeasSerial = p.buffer.MeasSerial
|
||||
|
||||
data := map[string]interface{}{}
|
||||
if p.buffer.MeasTcp.source == SOURCE_TCP {
|
||||
data[string(SOURCE_TCP)] = p.buffer.MeasTcp
|
||||
}
|
||||
if p.buffer.MeasSerial.source == SOURCE_SERIAL {
|
||||
data[string(SOURCE_SERIAL)] = p.buffer.MeasSerial
|
||||
}
|
||||
p.buffer.tcpMutex.Unlock()
|
||||
p.buffer.serialMutex.Unlock()
|
||||
|
||||
jdata, err := json.Marshal(data)
|
||||
//logrus.Println(string(pretty.Pretty(jdata)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.publisher.Publish(string(jdata))
|
||||
return nil
|
||||
}
|
||||
|
||||
type pipeBuffer struct {
|
||||
MeasTcp SensorData
|
||||
MeasSerial SensorData
|
||||
LastMeasTcp SensorData
|
||||
LastMeasSerial SensorData
|
||||
tcpMutex *sync.Mutex
|
||||
serialMutex *sync.Mutex
|
||||
}
|
||||
|
||||
type UnixNanoTime int64
|
||||
|
||||
type synchronizer struct {
|
||||
tcpSerialDelayMs int64
|
||||
mutex *sync.RWMutex
|
||||
updateTicker *time.Ticker
|
||||
}
|
||||
|
||||
func (p *pipeline) refreshDelay() error {
|
||||
logrus.Debugf("refreshing delay...")
|
||||
p.buffer.serialMutex.Lock()
|
||||
p.buffer.tcpMutex.Lock()
|
||||
tcpTime := p.buffer.MeasTcp.Timestamp
|
||||
serTime := p.buffer.MeasSerial.Timestamp
|
||||
p.buffer.tcpMutex.Unlock()
|
||||
p.buffer.serialMutex.Unlock()
|
||||
|
||||
if tcpTime.IsZero() || serTime.IsZero() || tcpTime.UnixNano() == 0 || serTime.UnixNano() == 0 {
|
||||
return errors.New("sync not possible. zero time value detected")
|
||||
}
|
||||
logrus.Debug("TCP", tcpTime.Format(time.RFC3339Nano))
|
||||
logrus.Debug("SER", serTime.Format(time.RFC3339Nano))
|
||||
|
||||
currentDelay := tcpTime.Sub(serTime).Milliseconds()
|
||||
p.synchroniz.mutex.Lock()
|
||||
defer p.synchroniz.mutex.Unlock()
|
||||
logrus.Debugf("old delay-> %vms...", p.synchroniz.tcpSerialDelayMs)
|
||||
if currentDelay > 5000 || currentDelay < -5000 {
|
||||
p.synchroniz.tcpSerialDelayMs = 0
|
||||
return errors.New("skipping synchronisation! time not properly configured or facing network problems.")
|
||||
}
|
||||
p.synchroniz.tcpSerialDelayMs += currentDelay
|
||||
logrus.Infof("new delay-> %vms", p.synchroniz.tcpSerialDelayMs)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *pipeline) pushTcpDataToBuffer(data SensorData) {
|
||||
data.Servertime = time.Now().UTC()
|
||||
|
||||
if p.isPipeRecording() {
|
||||
p.storer.Put(data)
|
||||
}
|
||||
|
||||
p.synchroniz.mutex.RLock()
|
||||
if p.synchroniz.tcpSerialDelayMs > 0 {
|
||||
time.Sleep(time.Duration(p.synchroniz.tcpSerialDelayMs) * time.Millisecond)
|
||||
}
|
||||
p.synchroniz.mutex.RUnlock()
|
||||
p.buffer.tcpMutex.Lock()
|
||||
p.buffer.MeasTcp = data
|
||||
//p.buffer.MeasTcp = p.buffer.MeasTcp.ConsolidateExTime(data)
|
||||
p.buffer.tcpMutex.Unlock()
|
||||
}
|
||||
func (p *pipeline) pushSerialDataToBuffer(data SensorData) {
|
||||
data.Servertime = time.Now().UTC()
|
||||
|
||||
if p.isPipeRecording() {
|
||||
p.storer.Put(data)
|
||||
}
|
||||
|
||||
p.synchroniz.mutex.RLock()
|
||||
if p.synchroniz.tcpSerialDelayMs < 0 {
|
||||
time.Sleep(time.Duration(-p.synchroniz.tcpSerialDelayMs) * time.Millisecond)
|
||||
}
|
||||
p.synchroniz.mutex.RUnlock()
|
||||
p.buffer.serialMutex.Lock()
|
||||
p.buffer.MeasSerial = data
|
||||
//p.buffer.MeasSerial = p.buffer.MeasSerial.ConsolidateEpochsOnly(data)
|
||||
p.buffer.serialMutex.Unlock()
|
||||
}
|
||||
|
||||
func (p *pipeline) Close() {
|
||||
p.mu.Lock()
|
||||
p.active = false
|
||||
p.mu.Unlock()
|
||||
}
|
||||
@ -5,36 +5,30 @@ import (
|
||||
ext "github.com/reugn/go-streams/extension"
|
||||
"github.com/reugn/go-streams/flow"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/tidwall/pretty"
|
||||
"time"
|
||||
)
|
||||
|
||||
type pipelineX struct {
|
||||
collNet *ext.ChanSource
|
||||
collSer *ext.ChanSource
|
||||
transNet *flow.FlatMap
|
||||
transSer *flow.FlatMap
|
||||
flowDelay *flow.Map
|
||||
flowStore *flow.Map
|
||||
flowJson *flow.Map
|
||||
sinkPub *publishSink
|
||||
}
|
||||
type pipelineRecord struct{}
|
||||
|
||||
func NewPipelineX(p Publisher, s Tracker, netChan chan interface{}, serialChan chan interface{}) *pipelineX {
|
||||
func NewRecordPipeline(p Publisher, s Tracker, netChan chan interface{}, serialChan chan interface{}) *pipelineRecord {
|
||||
// set pipeline up and wire it together
|
||||
collNet := ext.NewChanSource(netChan)
|
||||
collSer := ext.NewChanSource(serialChan)
|
||||
transNet := flow.NewFlatMap(transformNetFunc, 8)
|
||||
transSer := flow.NewFlatMap(transformSerFunc, 8)
|
||||
flowDelay := flow.NewMap(delayFunc(), 8)
|
||||
flowStore := flow.NewMap(storeFunc(s), 8)
|
||||
//flowJson := flow.NewMap(jsonFunc, 8)
|
||||
transNet := flow.NewFlatMap(transformNetFunc, 1)
|
||||
transSer := flow.NewFlatMap(transformSerFunc, 1)
|
||||
flowStore := flow.NewMap(storeFunc(s), 1)
|
||||
|
||||
dataSanitizer := flow.NewMap(replaySanitizeFunc(), 1)
|
||||
|
||||
flowJson := flow.NewMap(jsonFunc, 1)
|
||||
sinkPub := newPublishSink(p)
|
||||
|
||||
// wire up and execute
|
||||
demux := flow.Merge(collNet.Via(transNet), collSer.Via(transSer))
|
||||
//go demux.Via(flowDelay).Via(flowStore).Via(flowJson).To(sinkPub)
|
||||
go demux.Via(flowDelay).Via(flowStore).To(sinkPub)
|
||||
return &pipelineX{}
|
||||
go demux.Via(flowStore).Via(dataSanitizer).Via(flowJson).To(sinkPub)
|
||||
|
||||
return &pipelineRecord{}
|
||||
}
|
||||
|
||||
func storeFunc(s Tracker) flow.MapFunc {
|
||||
@ -53,34 +47,37 @@ func storeFunc(s Tracker) flow.MapFunc {
|
||||
}
|
||||
|
||||
logrus.Debugf("%-14v %-40s %-40s %v %v", sd.Source(), sd.Timestamp.Format(time.RFC3339Nano), sd.Servertime.Format(time.RFC3339Nano), sd.Position, sd.Orientation)
|
||||
|
||||
data := map[string]interface{}{}
|
||||
if sd.Source() == SOURCE_TCP {
|
||||
data[string(SOURCE_TCP)] = *sd
|
||||
}
|
||||
if sd.Source() == SOURCE_SERIAL {
|
||||
data[string(SOURCE_SERIAL)] = *sd
|
||||
}
|
||||
|
||||
jdata, err := json.Marshal(data)
|
||||
//logrus.Println(string(pretty.Pretty(jdata)))
|
||||
if err != nil {
|
||||
logrus.Fatalln(err)
|
||||
}
|
||||
return string(jdata)
|
||||
|
||||
//runtime.Gosched()
|
||||
return sd
|
||||
}
|
||||
}
|
||||
|
||||
type timeDelay struct {
|
||||
offsets map[SourceId]int
|
||||
}
|
||||
|
||||
func delayFunc() flow.MapFunc {
|
||||
//td := &timeDelay{}
|
||||
return func(i interface{}) interface{} {
|
||||
return i
|
||||
func jsonFunc(i interface{}) interface{} {
|
||||
var sd *SensorData
|
||||
switch v := i.(type) {
|
||||
case SensorData:
|
||||
sd = &v
|
||||
case *SensorData:
|
||||
sd = v
|
||||
default:
|
||||
panic("jsonFunc: wrong Type")
|
||||
}
|
||||
|
||||
data := map[string]interface{}{}
|
||||
if sd.Source() == SOURCE_TCP {
|
||||
data[string(SOURCE_TCP)] = *sd
|
||||
}
|
||||
if sd.Source() == SOURCE_SERIAL {
|
||||
data[string(SOURCE_SERIAL)] = *sd
|
||||
}
|
||||
|
||||
jdata, err := json.Marshal(data)
|
||||
logrus.Traceln(string(pretty.Pretty(jdata)))
|
||||
if err != nil {
|
||||
logrus.Fatalln(err)
|
||||
}
|
||||
return string(jdata)
|
||||
|
||||
}
|
||||
|
||||
func transformNetFunc(i interface{}) []interface{} {
|
||||
@ -115,6 +112,9 @@ func transformSerFunc(i interface{}) []interface{} {
|
||||
return append(returnSlice, sd)
|
||||
}
|
||||
|
||||
// Publish sink will pass data to dispatcher after flowing through the stream processing
|
||||
// matches api to use it with github.com/reugn/go-streams/flow
|
||||
|
||||
type publishSink struct {
|
||||
in chan interface{}
|
||||
p Publisher
|
||||
216
core/pipeline_replay.go
Normal file
216
core/pipeline_replay.go
Normal file
@ -0,0 +1,216 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"container/heap"
|
||||
"github.com/reugn/go-streams"
|
||||
ext "github.com/reugn/go-streams/extension"
|
||||
"github.com/reugn/go-streams/flow"
|
||||
"github.com/sirupsen/logrus"
|
||||
"runtime"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type pipelineReplay struct {
|
||||
stopChan chan struct{}
|
||||
replayChan chan interface{}
|
||||
}
|
||||
|
||||
func (p *pipelineReplay) Stop() {
|
||||
defer func() {
|
||||
if recover() != nil {
|
||||
logrus.Debugln("replay channel already closed")
|
||||
}
|
||||
}()
|
||||
logrus.Debugln("send stop signal...")
|
||||
select {
|
||||
case p.stopChan <- struct{}{}:
|
||||
logrus.Debugln("stop signal sent")
|
||||
//default:
|
||||
// logrus.Debugln("stop signal skipped")
|
||||
}
|
||||
}
|
||||
|
||||
func NewReplayPipeline(p Publisher, t *Tracking) *pipelineReplay {
|
||||
r := &pipelineReplay{make(chan struct{}), nil}
|
||||
// set pipeline up and wire it together
|
||||
r.replayChan = r.channelFromTracking(t)
|
||||
collNet := ext.NewChanSource(r.replayChan)
|
||||
dataSanitizer := flow.NewMap(replaySanitizeFunc(), 1)
|
||||
//flowReorder := NewRearranger()
|
||||
|
||||
flowJson := flow.NewMap(jsonFunc, 1)
|
||||
sinkPub := newPublishSink(p)
|
||||
|
||||
// wire up and execute
|
||||
//go collNet.Via(dataSanitizer).Via(flowJson).To(sinkPub)
|
||||
go collNet.Via(dataSanitizer).Via(flowJson).To(sinkPub)
|
||||
return r
|
||||
}
|
||||
|
||||
func (p *pipelineReplay) channelFromTracking(t *Tracking) chan interface{} {
|
||||
ch := make(chan interface{})
|
||||
sort.Slice(t.Data, func(i, j int) bool { return t.Data[i].Servertime.Before(t.Data[j].Servertime) })
|
||||
go func() {
|
||||
lastTs := t.Data[0].Servertime.UnixNano()
|
||||
lastTsNow := time.Now().UTC().UnixNano()
|
||||
i := 0
|
||||
br:
|
||||
for i <= len(t.Data)-1 {
|
||||
durationSinceLastEvent := t.Data[i].Servertime.UnixNano() - lastTs
|
||||
timeCounter := time.Now().UTC().UnixNano() - lastTsNow
|
||||
if timeCounter >= durationSinceLastEvent {
|
||||
logrus.Traceln("replay tracking: ", t.Data[i])
|
||||
ch <- &(t.Data[i])
|
||||
lastTs = t.Data[i].Servertime.UnixNano()
|
||||
lastTsNow = time.Now().UTC().UnixNano()
|
||||
i++
|
||||
}
|
||||
select {
|
||||
case <-p.stopChan:
|
||||
logrus.Debugln("received stop signal: replay stopped")
|
||||
break br
|
||||
default:
|
||||
}
|
||||
}
|
||||
logrus.Infoln("replay: tracking replay finished")
|
||||
select {
|
||||
case <-p.stopChan:
|
||||
logrus.Debugln("received stop signal: replay pipeline closed")
|
||||
}
|
||||
close(p.replayChan)
|
||||
}()
|
||||
return ch
|
||||
}
|
||||
|
||||
func replaySanitizeFunc() flow.MapFunc {
|
||||
var lastTimeOffsetIphone int64
|
||||
var lastTimeOffsetUblox int64
|
||||
|
||||
return func(i interface{}) interface{} {
|
||||
sd := i.(*SensorData)
|
||||
|
||||
if !(sd.Timestamp.IsZero() || sd.Timestamp.Nanosecond() == 0) {
|
||||
lastOffset := sd.Servertime.UnixNano() - sd.Timestamp.UnixNano()
|
||||
if sd.Source() == SOURCE_TCP {
|
||||
lastTimeOffsetIphone = lastOffset
|
||||
}
|
||||
if sd.Source() == SOURCE_SERIAL {
|
||||
lastTimeOffsetUblox = lastOffset
|
||||
}
|
||||
} else {
|
||||
var lastOff int64
|
||||
if sd.Source() == SOURCE_TCP {
|
||||
lastOff = lastTimeOffsetIphone
|
||||
}
|
||||
if sd.Source() == SOURCE_SERIAL {
|
||||
lastOff = lastTimeOffsetUblox
|
||||
}
|
||||
sd.Timestamp = sd.Servertime.Add(time.Duration(lastOff))
|
||||
}
|
||||
//if sd.Servertime.Before(time.Unix(1608422400, 0)) && sd.Speed != 0 && sd.Source() == SOURCE_SERIAL {
|
||||
// sd.Speed = sd.Speed * 3.6
|
||||
//}
|
||||
return sd
|
||||
}
|
||||
}
|
||||
|
||||
// The Rearranger is not used but kept, for later experiments.
|
||||
|
||||
func NewRearranger() *rearranger {
|
||||
rearran := &rearranger{
|
||||
queue: &flow.PriorityQueue{},
|
||||
in: make(chan interface{}),
|
||||
out: make(chan interface{}),
|
||||
done: make(chan struct{}),
|
||||
}
|
||||
go rearran.receive()
|
||||
go rearran.emit()
|
||||
return rearran
|
||||
}
|
||||
|
||||
type rearranger struct {
|
||||
sync.RWMutex
|
||||
queue *flow.PriorityQueue
|
||||
in chan interface{}
|
||||
out chan interface{}
|
||||
done chan struct{}
|
||||
lastTimestamp int64
|
||||
lastTimeNanoNow int64
|
||||
}
|
||||
|
||||
// Verify rearranger satisfies the Flow interface.
|
||||
var _ streams.Flow = (*rearranger)(nil)
|
||||
|
||||
func (r *rearranger) In() chan<- interface{} {
|
||||
return r.in
|
||||
}
|
||||
|
||||
func (r *rearranger) Out() <-chan interface{} {
|
||||
return r.out
|
||||
}
|
||||
|
||||
func (r *rearranger) Via(flow streams.Flow) streams.Flow {
|
||||
go r.transmit(flow)
|
||||
return flow
|
||||
}
|
||||
|
||||
func (r *rearranger) To(sink streams.Sink) {
|
||||
r.transmit(sink)
|
||||
}
|
||||
|
||||
// submit emitted windows to the next Inlet
|
||||
func (r *rearranger) transmit(inlet streams.Inlet) {
|
||||
for elem := range r.Out() {
|
||||
inlet.In() <- elem
|
||||
}
|
||||
close(inlet.In())
|
||||
}
|
||||
|
||||
func (r *rearranger) receive() {
|
||||
for elem := range r.in {
|
||||
ts := r.timestamp(elem)
|
||||
//if r.lastTimestamp == 0 {
|
||||
// r.lastTimestamp = ts //- (500 * 1e+6) // Delay
|
||||
// r.lastTimeNanoNow = time.Now().UTC().UnixNano()
|
||||
//}
|
||||
item := flow.NewItem(elem, ts, 0)
|
||||
r.Lock()
|
||||
heap.Push(r.queue, item)
|
||||
r.Unlock()
|
||||
logrus.Debugln("item recieved.")
|
||||
runtime.Gosched()
|
||||
}
|
||||
close(r.done)
|
||||
close(r.out)
|
||||
}
|
||||
|
||||
// emit pops data from ordered priority queue
|
||||
func (r *rearranger) emit() {
|
||||
for {
|
||||
if r.queue.Len() <= 10 {
|
||||
continue
|
||||
}
|
||||
tnow := time.Now().UTC().UnixNano()
|
||||
logrus.Debugln("popping item: ")
|
||||
|
||||
r.Lock()
|
||||
item := heap.Pop(r.queue).(*flow.Item)
|
||||
r.Unlock()
|
||||
v := item.Msg.(*SensorData)
|
||||
r.out <- v
|
||||
r.lastTimestamp = v.Timestamp.UnixNano()
|
||||
r.lastTimeNanoNow = tnow
|
||||
select {
|
||||
case <-r.done:
|
||||
return
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *rearranger) timestamp(elem interface{}) int64 {
|
||||
v := elem.(*SensorData)
|
||||
return v.Timestamp.UnixNano()
|
||||
}
|
||||
@ -1 +0,0 @@
|
||||
package core
|
||||
144
core/service.go
144
core/service.go
@ -10,6 +10,7 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// indicates state of the TrackingService
|
||||
type OpMode uint8
|
||||
|
||||
const (
|
||||
@ -19,21 +20,7 @@ const (
|
||||
REPLAY
|
||||
)
|
||||
|
||||
type Service interface {
|
||||
AllTrackings() ([]TrackingMetadata, error)
|
||||
StartPipeline(cols ...CollectorType) (string, error)
|
||||
StartRecord() (string, error)
|
||||
StopRecord() (*TrackingMetadata, error)
|
||||
StopAll() (*TrackingMetadata, error)
|
||||
|
||||
LoadTracking(trackingId uuid.UUID) (*Tracking, error)
|
||||
DeleteTracking(trackingId uuid.UUID)
|
||||
|
||||
StartReplay()
|
||||
PauseReplay()
|
||||
StopReplay()
|
||||
}
|
||||
|
||||
// structs implementing this interface are expected to cache sensor data passed by Put(data) while recording and dropping data if not recording
|
||||
type Tracker interface {
|
||||
Put(data SensorData)
|
||||
Recorder
|
||||
@ -44,37 +31,42 @@ type Recorder interface {
|
||||
IsRecording() bool
|
||||
}
|
||||
|
||||
type trackingService struct {
|
||||
opMode OpMode
|
||||
tracking *Tracking
|
||||
pipeline *pipelineX
|
||||
// this struct holds all relevant references for the TrackingService
|
||||
type TrackingService struct {
|
||||
opMode OpMode
|
||||
tracking *Tracking
|
||||
//pipeline *pipelineRecord
|
||||
replaypipe *pipelineReplay
|
||||
collectors []Collector
|
||||
store Storer
|
||||
publisher Publisher
|
||||
config *Configuration
|
||||
recSem *semaphore.Weighted
|
||||
mu *sync.RWMutex
|
||||
mu *sync.RWMutex
|
||||
}
|
||||
|
||||
func TrackingService(c *Configuration, s Storer, p Publisher) *trackingService {
|
||||
// constructor
|
||||
func NewTrackingService(c *Configuration, s Storer, p Publisher) *TrackingService {
|
||||
t := &Tracking{}
|
||||
ts := &trackingService{
|
||||
ts := &TrackingService{
|
||||
tracking: t,
|
||||
opMode: STOPPED,
|
||||
collectors: nil,
|
||||
recSem: semaphore.NewWeighted(1),
|
||||
mu: &sync.RWMutex{},
|
||||
mu: &sync.RWMutex{},
|
||||
config: c,
|
||||
store: s,
|
||||
publisher: p,
|
||||
}
|
||||
// first initialize of tcp collector to to open tcp port
|
||||
|
||||
// first call to to open tcp port. makes app ready to accept connections
|
||||
NewCollector(c, TCP)
|
||||
|
||||
return ts
|
||||
}
|
||||
|
||||
func (t *trackingService) Put(data SensorData) {
|
||||
// caches sensordata while recording
|
||||
func (t *TrackingService) Put(data SensorData) {
|
||||
if !t.IsRecording() {
|
||||
return
|
||||
}
|
||||
@ -85,7 +77,8 @@ func (t *trackingService) Put(data SensorData) {
|
||||
t.mu.Unlock()
|
||||
}
|
||||
|
||||
func (t *trackingService) SetRecording(s bool) (ok bool) {
|
||||
// changes recording state of service
|
||||
func (t *TrackingService) SetRecording(s bool) (ok bool) {
|
||||
if okay := t.recSem.TryAcquire(1); okay && s {
|
||||
// if i want to turn on and can get semaphore then return success
|
||||
return true
|
||||
@ -97,7 +90,7 @@ func (t *trackingService) SetRecording(s bool) (ok bool) {
|
||||
return false
|
||||
}
|
||||
|
||||
func (t *trackingService) IsRecording() bool {
|
||||
func (t *TrackingService) IsRecording() bool {
|
||||
if t.recSem.TryAcquire(1) {
|
||||
t.recSem.Release(1)
|
||||
return false
|
||||
@ -105,23 +98,27 @@ func (t *trackingService) IsRecording() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (t *trackingService) StartPipeline(cols ...CollectorType) (string, error) {
|
||||
// creates a new Pipeline with requested collectors
|
||||
func (t *TrackingService) StartLivetracking(cols ...CollectorType) (string, error) {
|
||||
logrus.Info("SERVICE: NEW PIPELINE")
|
||||
// check if state machine is in right state
|
||||
if t.opMode == RECORDING {
|
||||
txt := "trackingservice: please stop recording before resetting pipeline"
|
||||
logrus.Warn(txt)
|
||||
return "RECORDING", errors.New(txt)
|
||||
}
|
||||
if t.opMode == REPLAY {
|
||||
t.StopAll()
|
||||
}
|
||||
if t.opMode == LIVE {
|
||||
txt := "trackingservice: stop tracking running stream before creating new one"
|
||||
logrus.Warnln(txt)
|
||||
//t.StopAll()
|
||||
//time.Sleep(1000 * time.Millisecond)
|
||||
return "record already running since: " + t.tracking.TimeCreated.String(), errors.New(txt)
|
||||
}
|
||||
logrus.Debugln("new tracking:", cols)
|
||||
t.opMode = LIVE
|
||||
|
||||
// create and start collectors
|
||||
t.collectors = nil
|
||||
var tcp, ser chan interface{}
|
||||
for _, col := range cols {
|
||||
@ -138,20 +135,24 @@ func (t *trackingService) StartPipeline(cols ...CollectorType) (string, error) {
|
||||
t.safelyReplaceTracking(newTracking())
|
||||
t.tracking.Collectors = cols
|
||||
|
||||
t.pipeline = NewPipelineX(t.publisher, t, tcp, ser)
|
||||
// finally create pipeline
|
||||
NewRecordPipeline(t.publisher, t, tcp, ser)
|
||||
t.publisher.SetStreaming(true)
|
||||
logrus.Debugln("current State:", t.opMode)
|
||||
|
||||
//time.Sleep(3 * time.Second)
|
||||
return "LIVE", nil
|
||||
}
|
||||
|
||||
func (t *trackingService) AllTrackings() ([]TrackingMetadata, error) {
|
||||
// retrieves all trackings. metadata only.
|
||||
func (t *TrackingService) AllTrackings() ([]TrackingMetadata, error) {
|
||||
logrus.Info("SERVICE: GET ALL TRACKINGS")
|
||||
data, err := t.store.LoadAll()
|
||||
logrus.Debugln("current State:", t.opMode)
|
||||
return data, err
|
||||
}
|
||||
|
||||
func (t *trackingService) StartRecord() (string, error) {
|
||||
// starts recording and returns state
|
||||
func (t *TrackingService) StartRecord() (string, error) {
|
||||
logrus.Info("SERVICE: START RECORD")
|
||||
if t.opMode != LIVE {
|
||||
if t.opMode == RECORDING {
|
||||
@ -167,10 +168,12 @@ func (t *trackingService) StartRecord() (string, error) {
|
||||
t.opMode = RECORDING
|
||||
t.tracking.TimeCreated = time.Now()
|
||||
t.SetRecording(true)
|
||||
logrus.Debugln("current State:", t.opMode)
|
||||
return "record started at: " + t.tracking.TimeCreated.String(), nil
|
||||
}
|
||||
|
||||
func (t *trackingService) StopRecord() (*TrackingMetadata, error) {
|
||||
// stops recording and returns metadata of current tracking if successfully stopped
|
||||
func (t *TrackingService) StopRecord() (*TrackingMetadata, error) {
|
||||
logrus.Info("SERVICE: STOP RECORD")
|
||||
if t.opMode != RECORDING {
|
||||
txt := "trackingservice: couldn't stop. not recording"
|
||||
@ -185,57 +188,92 @@ func (t *trackingService) StopRecord() (*TrackingMetadata, error) {
|
||||
logrus.Error(err)
|
||||
}
|
||||
t.opMode = LIVE
|
||||
//time.Sleep(20 * time.Millisecond)
|
||||
|
||||
tm := t.tracking.TrackingMetadata
|
||||
t.safelyReplaceTracking(newTracking())
|
||||
t.tracking.Collectors = tm.Collectors
|
||||
logrus.Debugln("current State:", t.opMode)
|
||||
return &tm, err
|
||||
}
|
||||
|
||||
func (t *trackingService) StopAll() (*TrackingMetadata, error) {
|
||||
// stops live tracking and recording. if theres no active recording, no metadata will be returned
|
||||
func (t *TrackingService) StopAll() (*TrackingMetadata, error) {
|
||||
logrus.Info("SERVICE: STOP ALL")
|
||||
var tm *TrackingMetadata = nil
|
||||
var err error
|
||||
t.publisher.SetStreaming(false)
|
||||
for _, e := range t.collectors {
|
||||
e.Stop()
|
||||
}
|
||||
if t.replaypipe != nil {
|
||||
t.replaypipe.Stop()
|
||||
t.replaypipe = nil
|
||||
}
|
||||
// let buffer run empty after collectors stopped
|
||||
time.Sleep(time.Millisecond * 5)
|
||||
t.publisher.SetStreaming(false)
|
||||
if t.opMode == RECORDING {
|
||||
logrus.Info("trackingservice: gracefully stop recording ")
|
||||
tm, err = t.StopRecord()
|
||||
}
|
||||
t.opMode = STOPPED
|
||||
logrus.Debugln("current State:", t.opMode)
|
||||
return tm, err
|
||||
}
|
||||
|
||||
func (t *trackingService) LoadTracking(trackingId uuid.UUID) (*Tracking, error) {
|
||||
// retrieves tracking with all data and starts replay pipeline if desired.
|
||||
// in that case the application behaves like in live mode.
|
||||
func (t *TrackingService) LoadTracking(trackingId uuid.UUID, replay bool) (*Tracking, error) {
|
||||
logrus.Info("SERVICE: LOAD TRACKING")
|
||||
if t.opMode == RECORDING {
|
||||
txt := "trackingservice: please stop recording before load another tracking"
|
||||
logrus.Warn(txt)
|
||||
return nil, errors.New(txt)
|
||||
}
|
||||
if t.opMode == REPLAY || t.opMode == LIVE {
|
||||
t.StopAll()
|
||||
}
|
||||
logrus.Info("LOAD TRACKING from database")
|
||||
tracking, err := t.store.Load(trackingId)
|
||||
fixSpeedValues(tracking)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if replay == false {
|
||||
return tracking, nil
|
||||
}
|
||||
t.safelyReplaceTracking(*tracking)
|
||||
if t.replaypipe != nil {
|
||||
select {
|
||||
case <-t.replaypipe.stopChan:
|
||||
logrus.Warnln("blocking channel closed")
|
||||
default:
|
||||
}
|
||||
t.replaypipe = nil
|
||||
}
|
||||
t.replaypipe = NewReplayPipeline(t.publisher, t.tracking)
|
||||
t.publisher.SetStreaming(true)
|
||||
t.opMode = REPLAY
|
||||
logrus.Debugln("current State:", t.opMode)
|
||||
return t.tracking, nil
|
||||
}
|
||||
|
||||
func (t *trackingService) DeleteTracking(trackingId uuid.UUID) {
|
||||
func (t *TrackingService) DeleteTracking(trackingId uuid.UUID) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (t *trackingService) StartReplay() {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (t *trackingService) PauseReplay() {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (t *trackingService) StopReplay() {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (t *trackingService) safelyReplaceTracking(tr Tracking) {
|
||||
// helper function to replace tracking held by service. makes sure to keep the pointer and change only underlying data.
|
||||
func (t *TrackingService) safelyReplaceTracking(tr Tracking) {
|
||||
t.recSem.Acquire(context.Background(), 1)
|
||||
*t.tracking = tr
|
||||
t.recSem.Release(1)
|
||||
}
|
||||
|
||||
// helper function to fixSpeedValues wrong values recorded before 12/20/2020
|
||||
func fixSpeedValues(tracking *Tracking) {
|
||||
logrus.Debugln("fixing speed values")
|
||||
for i := 0; i < len(tracking.Data); i++ {
|
||||
if tracking.Data[i].Servertime.Before(time.Unix(1608422400, 0)) && tracking.Data[i].Source() == SOURCE_SERIAL && tracking.Data[i].Speed != 0 {
|
||||
tracking.Data[i].Speed = tracking.Data[i].Speed * 3.6
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BIN
devdocs.pdf
Normal file
BIN
devdocs.pdf
Normal file
Binary file not shown.
@ -10,11 +10,6 @@ collectors:
|
||||
porttcp: ":3010"
|
||||
portserial: "/dev/tty.usbmodem14201"
|
||||
|
||||
# processing pipeline configurations
|
||||
pipeline:
|
||||
publishIntervalMs: 50
|
||||
syncUpdateIntervalMs: 494
|
||||
|
||||
debuglevel: "INFO"
|
||||
|
||||
#// ErrorLevel level. Logs. Used for errors that should definitely be noted.
|
||||
@ -29,4 +24,4 @@ debuglevel: "INFO"
|
||||
#InfoLevel
|
||||
|
||||
#// DebugLevel level. Usually only enabled when debugging. Very verbose logging.
|
||||
#DebugLevel
|
||||
#DebugLevel
|
||||
|
||||
12
go.mod
12
go.mod
@ -3,18 +3,24 @@ module git.timovolkmann.de/gyrogpsc
|
||||
go 1.15
|
||||
|
||||
require (
|
||||
github.com/DataDog/zstd v1.4.6-0.20200617134701-89f69fb7df32 // indirect
|
||||
github.com/dgraph-io/badger/v2 v2.2007.2
|
||||
github.com/fsnotify/fsnotify v1.4.9 // indirect
|
||||
github.com/gofiber/fiber/v2 v2.2.4
|
||||
github.com/gofiber/template v1.6.6
|
||||
github.com/gofiber/websocket/v2 v2.0.2
|
||||
github.com/google/go-cmp v0.5.2
|
||||
github.com/golang/protobuf v1.4.2 // indirect
|
||||
github.com/google/go-cmp v0.5.2 // indirect
|
||||
github.com/google/uuid v1.1.2
|
||||
github.com/reugn/go-streams v0.5.2
|
||||
github.com/klauspost/compress v1.11.0 // indirect
|
||||
github.com/reugn/go-streams v0.6.3
|
||||
github.com/sirupsen/logrus v1.6.0
|
||||
github.com/spf13/viper v1.7.1
|
||||
github.com/tidwall/gjson v1.6.0
|
||||
github.com/tidwall/pretty v1.0.2
|
||||
go.bug.st/serial v1.1.1
|
||||
go.bug.st/serial v1.1.3
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e
|
||||
golang.org/x/sys v0.0.0-20201211090839-8ad439b19e0f // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect
|
||||
)
|
||||
|
||||
160
go.sum
160
go.sum
@ -11,14 +11,11 @@ cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqCl
|
||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/99designs/keyring v1.1.5 h1:wLv7QyzYpFIyMSwOADq1CLTF9KbjbBfcnfmOGJ64aO4=
|
||||
github.com/99designs/keyring v1.1.5/go.mod h1:7hsVvt2qXgtadGevGJ4ujg+u8m6SpJ5TpHqTozIPqf0=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno=
|
||||
github.com/CloudyKit/jet/v3 v3.0.1/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo=
|
||||
github.com/DataDog/zstd v1.4.1 h1:3oxKN3wbHibqx897utPC2LTQU4J+IHWWJO+glkAkpFM=
|
||||
github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
|
||||
github.com/DataDog/zstd v1.4.6-0.20200617134701-89f69fb7df32 h1:/gZKpgSMydtrih81nvUhlkXpZIUfthKShSCVbRzBt9Y=
|
||||
github.com/DataDog/zstd v1.4.6-0.20200617134701-89f69fb7df32/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
|
||||
@ -30,48 +27,24 @@ github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF0
|
||||
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM=
|
||||
github.com/Shopify/sarama v1.27.1 h1:iUlzHymqWsITyttu6KxazcAz8WEj5FqcwFK/oEi7rE8=
|
||||
github.com/Shopify/sarama v1.27.1/go.mod h1:g5s5osgELxgM+Md9Qni9rzo7Rbt+vvFQI4bt/Mc93II=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
||||
github.com/aerospike/aerospike-client-go v3.1.0+incompatible h1:ggcqXpZOCBlMptXPooX9MQfOa8aKIPhdCqLwAjR5M9U=
|
||||
github.com/aerospike/aerospike-client-go v3.1.0+incompatible/go.mod h1:zj8LBEnWBDOVEIJt8LvaRvDG5ARAoa5dBeHaB472NRc=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/andybalholm/brotli v1.0.0 h1:7UCwP93aiSfvWpapti8g88vVVGp2qqtGyePsSuDafo4=
|
||||
github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||
github.com/apache/pulsar-client-go v0.2.0 h1:7teu0FaXzzKPjDdUNjA7dVYKFjCy6OVX5as6nUww4qk=
|
||||
github.com/apache/pulsar-client-go v0.2.0/go.mod h1:POSPPmXv1RuoM7FzHaS3NurCSOopwin2ekGK2PcOgVM=
|
||||
github.com/apache/pulsar-client-go/oauth2 v0.0.0-20200715083626-b9f8c5cedefb h1:E1P0FudxDdj2RhbveZC9i3PwukLCA/4XQSkBS/dw6/I=
|
||||
github.com/apache/pulsar-client-go/oauth2 v0.0.0-20200715083626-b9f8c5cedefb/go.mod h1:0UtvvETGDdvXNDCHa8ZQpxl+w3HbdFtfYZvDHLgWGTY=
|
||||
github.com/ardielle/ardielle-go v1.5.2 h1:TilHTpHIQJ27R1Tl/iITBzMwiUGSlVfiVhwDNGM3Zj4=
|
||||
github.com/ardielle/ardielle-go v1.5.2/go.mod h1:I4hy1n795cUhaVt/ojz83SNVCYIGsAFAONtv2Dr7HUI=
|
||||
github.com/ardielle/ardielle-tools v1.5.4/go.mod h1:oZN+JRMnqGiIhrzkRN9l26Cej9dEx4jeNG6A+AdkShk=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/aymerick/raymond v2.0.2+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
|
||||
github.com/beefsack/go-rate v0.0.0-20180408011153-efa7637bb9b6/go.mod h1:6YNgTHLutezwnBvyneBbwvB8C82y3dcoOj5EQJIdGXA=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
||||
github.com/bmizerany/perks v0.0.0-20141205001514-d9a9656a3a4b/go.mod h1:ac9efd0D1fsDb3EJvhqgXRbFx7bs2wqZ10HQPeU8U/Q=
|
||||
github.com/bombsimon/wsl/v3 v3.1.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc=
|
||||
github.com/boynton/repl v0.0.0-20170116235056-348863958e3e/go.mod h1:Crc/GCZ3NXDVCio7Yr0o+SSrytpcFhLmVCIzi0s49t4=
|
||||
github.com/cbroglie/mustache v1.2.0/go.mod h1:gomHsVlF4zTcsY2H8d7U9SipCYbbrAks5breARbqAM0=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
@ -85,9 +58,9 @@ github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwc
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/goselect v0.1.1 h1:tiSSgKE1eJtxs1h/VgGQWuXUP0YS4CDIFMp6vaI1ls0=
|
||||
github.com/creack/goselect v0.1.1/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY=
|
||||
github.com/creack/goselect v0.1.2 h1:2DNy14+JPjRBgPzAd1thbQp4BSIihxcBf0IXhQXDRa0=
|
||||
github.com/creack/goselect v0.1.2/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/danieljoos/wincred v1.0.2/go.mod h1:SnuYRW9lp1oJrZX/dXJqr0cPK5gYXqx3EJbmjhLdK9U=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@ -96,31 +69,18 @@ github.com/dgraph-io/badger/v2 v2.2007.2 h1:EjjK0KqwaFMlPin1ajhP943VPENHJdEz1KLI
|
||||
github.com/dgraph-io/badger/v2 v2.2007.2/go.mod h1:26P/7fbL4kUZVEVKLAKXkBXKOydDmM2p1e+NhhnBCAE=
|
||||
github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de h1:t0UHb5vdojIDUqktM6+xJAfScFBsVpXZmqC9dsgJmeA=
|
||||
github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA=
|
||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/dimfeld/httptreemux v5.0.1+incompatible/go.mod h1:rbUlSV+CCpv/SuqUTP/8Bk2O3LyUV436/yaRGkhP6Z0=
|
||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dvsekhvalnov/jose2go v0.0.0-20180829124132-7f401d37b68a h1:mq+R6XEM6lJX5VlLyZIrUSP8tSuJp82xTK89hvBwJbU=
|
||||
github.com/dvsekhvalnov/jose2go v0.0.0-20180829124132-7f401d37b68a/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM=
|
||||
github.com/eapache/go-resiliency v1.2.0 h1:v7g92e/KSN71Rq7vSThKaWIq68fL4YHvWyiUKorFR1Q=
|
||||
github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 h1:YEetp8/yCZMuEPMUDHG0CW/brkkEp8mzqk2+ODEitlw=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||
github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc=
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM=
|
||||
github.com/fasthttp/websocket v1.4.3 h1:qjhRJ/rTy4KB8oBxljEC00SDt6HUY9jLRfM601SUdS4=
|
||||
github.com/fasthttp/websocket v1.4.3/go.mod h1:5r4oKssgS7W6Zn6mPWap3NWzNPJNzUUh3baWTOhcYQk=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||
github.com/flosch/pongo2/v4 v4.0.1/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8=
|
||||
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||
github.com/frankban/quicktest v1.10.2/go.mod h1:K+q6oSqb0W0Ininfk863uOk1lMy69l/P6txr3mVT54s=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
@ -128,13 +88,10 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME
|
||||
github.com/go-critic/go-critic v0.5.0/go.mod h1:4jeRh3ZAVnRYhuWdOEvwzVqLUpxMSoAT0xZ74JsTPlo=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-lintpack/lintpack v0.5.2/go.mod h1:NwZuYi2nUHho8XEIZ6SIxihrnPoqBTDqfpXvXAN0sXM=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
|
||||
github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
|
||||
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4=
|
||||
@ -153,7 +110,6 @@ github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2
|
||||
github.com/go-toolsmith/typep v1.0.2/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU=
|
||||
github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM=
|
||||
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
|
||||
github.com/gofiber/fiber/v2 v2.1.0/go.mod h1:aG+lMkwy3LyVit4CnmYUbUdgjpc3UYOltvlJZ78rgQ0=
|
||||
github.com/gofiber/fiber/v2 v2.2.2/go.mod h1:Aso7/M+EQOinVkWp4LUYjdlTpKTBoCk2Qo4djnMsyHE=
|
||||
github.com/gofiber/fiber/v2 v2.2.4 h1:t2V2SxlbQGdt8+SS/Mo+tQB0pDQn7OajKdA72qHcBVw=
|
||||
@ -165,8 +121,6 @@ github.com/gofiber/websocket/v2 v2.0.2/go.mod h1:7VBnzEVRK0K0eTIVc5GbXPF1JWUFnll
|
||||
github.com/gofrs/flock v0.7.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
|
||||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
@ -174,7 +128,6 @@ github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
@ -203,14 +156,11 @@ github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
@ -223,17 +173,13 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m
|
||||
github.com/gookit/color v1.2.4/go.mod h1:AhIE+pS6D4Ql0SQWbBeXPHw7gY0/sjHoA4s/n1KB7xg=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE=
|
||||
github.com/gostaticanalysis/analysisutil v0.0.3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0=
|
||||
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
@ -246,8 +192,6 @@ github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerX
|
||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE=
|
||||
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
@ -259,43 +203,29 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jawher/mow.cli v1.0.4/go.mod h1:5hQj2V8g+qYmLUVWqu4Wuja1pI57M83EChYLVZ0sMKk=
|
||||
github.com/jawher/mow.cli v1.1.0/go.mod h1:aNaQlc7ozF3vw6IJ2dHjp2ZFiA4ozMIYY6PyuRJwlUg=
|
||||
github.com/jcmturner/gofork v1.0.0 h1:J7uCkflzTEhUZ64xqKnkDxq3kzc96ajM1Gli5ktUem8=
|
||||
github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
|
||||
github.com/jingyugao/rowserrcheck v0.0.0-20191204022205-72ab7603b68a/go.mod h1:xRskid8CManxVta/ALEhJha/pweKBaVG6fWgc0yH25s=
|
||||
github.com/jirfag/go-printf-func-name v0.0.0-20191110105641-45db9963cdd3/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0=
|
||||
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
|
||||
github.com/jmoiron/sqlx v1.2.1-0.20190826204134-d7d95172beb5/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d h1:Z+RDyXzjKE0i2sTjZ/b1uxiGtPhFy34Ou/Tk0qwN0kM=
|
||||
github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d/go.mod h1:JJNrCn9otv/2QP4D7SMJBgaleKpOf66PnW6F5WGNRIc=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.10.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.10.5/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.10.7 h1:7rix8v8GpI3ZBb0nSozFRgbtXKv+hOe+qfEpZqybrAg=
|
||||
github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.10.8/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.11.0 h1:wJbzvpYMVGG9iTI9VxpnNZfd4DzMPoCWze3GgSqz8yg=
|
||||
github.com/klauspost/compress v1.11.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
@ -317,12 +247,10 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky
|
||||
github.com/mattn/go-slim v0.0.0-20200618151855-bde33eecb5ee/go.mod h1:ma9TUJeni8LGZMJvOwbAv/FOwiwqIMQN570LnpqCBSM=
|
||||
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
@ -331,39 +259,26 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mozilla/tls-observatory v0.0.0-20200317151703-4fa42e1c2dee/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk=
|
||||
github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs=
|
||||
github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nakabonne/nestif v0.3.0/go.mod h1:dI314BppzXjJ4HsCnbo7XzrJHPszZsjnk5wEBSYHI2c=
|
||||
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nishanths/exhaustive v0.0.0-20200525081945-8e46705b6132/go.mod h1:wBEpHwM2OdmeNpdCvRPUlkEbBuaFmcK4Wv8Q7FuGW3c=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pierrec/lz4 v2.5.2+incompatible h1:WCjObylUIOlKy/+7Abdn34TLIkXiA4UWUMhxq9m9ZXI=
|
||||
github.com/pierrec/lz4 v2.5.2+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
@ -372,31 +287,18 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.7.1 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA=
|
||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
|
||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc=
|
||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8=
|
||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI=
|
||||
github.com/quasilyte/go-ruleguard v0.1.2-0.20200318202121-b00d7a75d3d8/go.mod h1:CGFX09Ci3pq9QZdj86B+VGIdNj4VyCo2iPOGS9esB/k=
|
||||
github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/reugn/go-streams v0.5.2 h1:LlNx/CjqA+/B0q1hk3uQTEUGuXrqX4JwcwVsXhfgdFA=
|
||||
github.com/reugn/go-streams v0.5.2/go.mod h1:j5OY7xE5VAdc6tHfCVsazjyX0ujVKlGwaBXlW/DXnuE=
|
||||
github.com/reugn/go-streams v0.6.3 h1:b+RqXgcKyOKxU5aX1ddIXCia1UBGeNpO/+yzo0CBVuE=
|
||||
github.com/reugn/go-streams v0.6.3/go.mod h1:OsEa/+BuietQY5sJUCm5nrZujfWtuKIv7KQVCZCXYGg=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.5.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
@ -415,7 +317,6 @@ github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxr
|
||||
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||
@ -432,12 +333,10 @@ github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
||||
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
|
||||
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
@ -448,10 +347,8 @@ github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk=
|
||||
github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
@ -485,19 +382,15 @@ github.com/valyala/fasthttp v1.17.0/go.mod h1:jjraHZVbKOXftJfsOYoAjaeygpj5hr8erm
|
||||
github.com/valyala/quicktemplate v1.5.0/go.mod h1:v7yYWpBEiutDyNfVaph6oC/yKwejzVyTX/2cwwHxyok=
|
||||
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a h1:0R4NLDRDZX6JcmhJgXi5E4b8Wg84ihbmUKp/GvSPEzc=
|
||||
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
|
||||
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
|
||||
github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
github.com/yahoo/athenz v1.8.55 h1:xGhxN3yLq334APyn0Zvcc+aqu78Q7BBhYJevM3EtTW0=
|
||||
github.com/yahoo/athenz v1.8.55/go.mod h1:G7LLFUH7Z/r4QAB7FfudfuA7Am/eCzO1GlzBhDL6Kv0=
|
||||
github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/gopher-lua v0.0.0-20200816102855-ee81675732da h1:NimzV1aGyq29m5ukMK0AMWEhFaL/lrEOaephfuoiARg=
|
||||
github.com/yuin/gopher-lua v0.0.0-20200816102855-ee81675732da/go.mod h1:E1AXubJBdNmFERAOucpDIxNzeGfLzg0mYh+UfMWdChA=
|
||||
go.bug.st/serial v1.1.1 h1:5J1DpaIaSIruBi7jVnKXnhRS+YQ9+2PLJMtIZKoIgnc=
|
||||
go.bug.st/serial v1.1.1/go.mod h1:VmYBeyJWp5BnJ0tw2NUJHZdJTGl2ecBGABHlzRK1knY=
|
||||
go.bug.st/serial v1.1.3 h1:YEBxJa9pKS9Wdg46B/jiaKbvvbUrjhZZZITfJHEJhaE=
|
||||
go.bug.st/serial v1.1.3/go.mod h1:8TT7u/SwwNIpJ8QaG4s+HTjFt9ReXs2cdOU7ZEk50Dk=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
@ -510,11 +403,8 @@ golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnf
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM=
|
||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@ -552,27 +442,19 @@ golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201016165138-7b1cca2348c0 h1:5kGOVHlq0euqwzgTC9Vu15p6fV1Wi0ArVi8da2urnVg=
|
||||
golang.org/x/net v0.0.0-20201016165138-7b1cca2348c0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@ -584,7 +466,6 @@ golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5h
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -595,23 +476,16 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201211090839-8ad439b19e0f h1:QdHQnPce6K4XQewki9WNbG5KOROuDzqO3NaYjI1cXJ0=
|
||||
golang.org/x/sys v0.0.0-20201211090839-8ad439b19e0f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -625,7 +499,6 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxb
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181117154741-2ddaf7f79a09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@ -644,7 +517,6 @@ golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgw
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190719005602-e377ae9d6386/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
|
||||
golang.org/x/tools v0.0.0-20190808195139-e713427fea3f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
@ -665,7 +537,6 @@ golang.org/x/tools v0.0.0-20200625211823-6506e20df31f/go.mod h1:EkVYQZoAsY45+roY
|
||||
golang.org/x/tools v0.0.0-20200702044944-0cc1aa72b347/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@ -699,11 +570,8 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
|
||||
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U=
|
||||
@ -712,31 +580,15 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
|
||||
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/jcmturner/aescts.v1 v1.0.1 h1:cVVZBK2b1zY26haWB4vbBiZrfFQnfbTVrE3xZq6hrEw=
|
||||
gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo=
|
||||
gopkg.in/jcmturner/dnsutils.v1 v1.0.1 h1:cIuC1OLRGZrld+16ZJvvZxVJeKPsvd5eUIvxfoN5hSM=
|
||||
gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q=
|
||||
gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4=
|
||||
gopkg.in/jcmturner/gokrb5.v7 v7.5.0 h1:a9tsXlIDD9SKxotJMK3niV7rPZAJeX2aD/0yg3qlIrg=
|
||||
gopkg.in/jcmturner/gokrb5.v7 v7.5.0/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM=
|
||||
gopkg.in/jcmturner/rpc.v1 v1.1.0 h1:QHIUxTX1ISuAv9dD2wJ9HWQVuWDX/Zc0PfeC2tjc4rU=
|
||||
gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/square/go-jose.v2 v2.4.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
51
readme.md
Normal file
51
readme.md
Normal file
@ -0,0 +1,51 @@
|
||||
# gyropsc ⚡
|
||||
**Realtime Location Dashboard 🚀**
|
||||
|
||||
Comprehensive documentation can be found [here](/tvolkmann/gyrogpsc/src/branch/develop/devdocs.pdf).
|
||||
|
||||
# Quickstart
|
||||
First copy `example_config.yml` to `gpsconfig.yml` and adjust your parameters. if you intend to use this tool with ublox over USB or Serial, you need to set the name of your port in this config file. otherwise the program will panic.
|
||||
|
||||
## Requirements
|
||||
* Win, Linux or Mac Computer, ideally with serial port and WiFi
|
||||
* GPS device (Android or iOS smartphone and/or ublox 8/M8 series module)
|
||||
* download latest release and unzip it
|
||||
|
||||
## Preparation
|
||||
Make sure you prepared your GPS device like described in chapter 3.3 of the Documentation.
|
||||
Start gyrogpsc **before** connecting your smartphone via TCP. Make sure you updated the config file with the correct COM port for your ublox device, before starting the Serial Collector from the UI.
|
||||
|
||||
## Run
|
||||
Execute `gyropgsc-$OS`, according to your operating system. Make sure the containing folder is your working directory.
|
||||
|
||||
|
||||
# Build and run from source
|
||||
## Requirements
|
||||
* git
|
||||
* go >1.15
|
||||
|
||||
## Run
|
||||
1. `git clone --recursive https://git.timovolkmann.de/tvolkmann/gyrogpsc.git`
|
||||
2. run `go install` from project root
|
||||
3. run `go run cmd/server/server.go` from project root to start application or just `go build cmd/server/server.go` for building it only
|
||||
4. open `http://localhost:3011`
|
||||
|
||||
## Build
|
||||
For your platform only: `go build cmd/server/server.go`
|
||||
|
||||
**Cross-Platform Builds:**
|
||||
|
||||
For Windows 64-bit: `GOOS=windows GOARCH=amd64 go build -o gyrogpsc-win.exe cmd/server/server.go`
|
||||
|
||||
For MacOS: `GOOS=darwin GOARCH=amd64 go build -o gyrogpsc-mac cmd/server/server.go`
|
||||
|
||||
For Linux: `GOOS=linux GOARCH=arm64 go build -o gyrogpsc-linux cmd/server/server.go`
|
||||
|
||||
Make sure that binaries have execute permissions on Mac and Linux. Currently only working on 64-bit systems. Cross Platform commands only working on Mac & Linux.
|
||||
|
||||
## Static files and demo database
|
||||
### Demo database
|
||||
To use demo data, copy `backups/_db-210115-01/` to folder `_db/` in project root. The prebuilt binaries zip-file already contains demo data.
|
||||
|
||||
### Static files
|
||||
All static files (`static/` and `templates/`) must be in the root of working directory when running gyrogpsc. That's already the case if you follow "Run" instructions.
|
||||
1
static/indicators
Submodule
1
static/indicators
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 8e879d5461753b0f06e171847408e618d51c9838
|
||||
56
static/replayStyle.css
Normal file
56
static/replayStyle.css
Normal file
@ -0,0 +1,56 @@
|
||||
body { margin: 0; padding: 0; }
|
||||
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
|
||||
|
||||
.legend {
|
||||
background-color: #fff;
|
||||
border-radius: 3px;
|
||||
bottom: 30px;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
|
||||
font: 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif;
|
||||
padding: 10px;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.legend h4 {
|
||||
margin: 0 0 10px;
|
||||
}
|
||||
|
||||
.legend div span {
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
height: 10px;
|
||||
margin-right: 5px;
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
body{margin:0; padding:0; font-size:13px; font-family:Georgia, "Times New Roman", Times, serif; color:#919191; background-color:#232323;}
|
||||
|
||||
.float-child {
|
||||
width: 45%;
|
||||
float: left;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
canvas {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.sceneMap {
|
||||
width: 1000px;
|
||||
height: 500px;
|
||||
border: 0px solid #CCC;
|
||||
margin: 20px;
|
||||
perspective: 400px;
|
||||
}
|
||||
|
||||
.scene {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
border: 0px solid #CCC;
|
||||
margin: 70px;
|
||||
perspective: 400px;
|
||||
}
|
||||
|
||||
label { margin-right: 10px; }
|
||||
114
static/scripts/accChart.js
Normal file
114
static/scripts/accChart.js
Normal file
@ -0,0 +1,114 @@
|
||||
/**
|
||||
* This file defines a line chart used in the full replay page, showing Ublox horizontal accuracy,
|
||||
* smartphone horizontal accuracy and distance between the positions of the Ublox
|
||||
* and the Smartphone at a same time in meters, over time.
|
||||
*
|
||||
* @authors Timo Volkmann, Frank Herkommer.
|
||||
*/
|
||||
|
||||
//list of all horizontal accuracies sent in by the Ublox
|
||||
let allAccSerial = []
|
||||
//list of all coordinates sent in by the Ublox
|
||||
let allSerialCoords = []
|
||||
|
||||
//Defines the chart and its properties
|
||||
let ctx1 = document.getElementById('accChart').getContext('2d');
|
||||
let accChart = new Chart(ctx1, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: [],
|
||||
datasets: [{
|
||||
label: 'Ublox Horizontal acc. (m)',
|
||||
backgroundColor: 'rgba(255, 255, 255, 1)',
|
||||
borderColor: 'rgba(255, 255, 255, 1)',
|
||||
borderWidth: 1,
|
||||
fill: false,
|
||||
pointRadius: 0.5,
|
||||
lineTension: 0.5,
|
||||
data: []
|
||||
},
|
||||
{
|
||||
label: 'Smartphone Horizontal acc. (m)',
|
||||
backgroundColor: 'rgb(185,190,45)',
|
||||
borderColor: 'rgb(185,190,45)',
|
||||
borderWidth: 1,
|
||||
fill: false,
|
||||
pointRadius: 0.5,
|
||||
lineTension: 0.5,
|
||||
data: []
|
||||
},
|
||||
{
|
||||
label: 'Distance Ublox - Smartphone (m)',
|
||||
backgroundColor: 'rgba(30, 130, 76, 1)',
|
||||
borderColor: 'rgba(30, 130, 76, 1)',
|
||||
borderWidth: 1,
|
||||
fill: false,
|
||||
pointRadius: 0.5,
|
||||
lineTension: 0.5,
|
||||
data: []
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
scales: {
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
min: 0,
|
||||
max: 20,
|
||||
}
|
||||
}],
|
||||
xAxes: [{
|
||||
type: 'time',
|
||||
time: {
|
||||
unit: 'second'
|
||||
}
|
||||
}]
|
||||
},
|
||||
animation: {
|
||||
duration: 0
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Function to calculate the distance between to coordinates at a same time using the vincenty algorithm.
|
||||
*
|
||||
* @param data all collected data.
|
||||
*/
|
||||
function addDistances(data){
|
||||
//collect all horizontal accuracies from serial source and tcp source.
|
||||
let serialHAccs = data.filter(el => el.ser != null).map(el => {
|
||||
return el.ser.HAcc
|
||||
})
|
||||
let tcpHAccs = data.filter(el => el.tcp != null).map(el => {
|
||||
return el.tcp.HAcc
|
||||
})
|
||||
//apply vincenty algorithm on coordinates from serial and tcp source.
|
||||
let distances = data.filter(el => el.ser != null && el.tcp != null).map((el, i, arr) => {
|
||||
// return distVincenty(el.ser.Position, el.tcp.Position)
|
||||
const plaindist = distVincenty(el.ser.Position, el.tcp.Position)
|
||||
arr[i]['distance'] = plaindist
|
||||
|
||||
// if closest measurements not happening in the exact same millisecond,
|
||||
// calculate traveled distance for the time difference and substract it from result
|
||||
// bear in mind that this is not exact because the two measurements are not always exactly aligned with
|
||||
// the direction of motion. that's okay because we only need to estimate the accuracy
|
||||
arr[i]['distanceCleanAbs'] = plaindist - Math.abs(el.ser.Speed / 1000 * el.differenceMs)
|
||||
return arr[i].distanceCleanAbs // plaindist - Math.abs(el.ser.Speed / 1000 * el.differenceMs)
|
||||
})
|
||||
|
||||
let timelabels = data.filter(el => el.tcp != null).map(el => {
|
||||
return el.tcp.Timestamp
|
||||
})
|
||||
if (timelabels.length === 0) {
|
||||
timelabels = data.filter(el => el.ser != null).map(el => {
|
||||
return el.ser.Timestamp
|
||||
})
|
||||
}
|
||||
|
||||
//add the data to the chart and update the hart
|
||||
accChart.data.labels = timelabels
|
||||
accChart.data.datasets[0].data = serialHAccs
|
||||
accChart.data.datasets[1].data = tcpHAccs
|
||||
accChart.data.datasets[2].data = distances
|
||||
accChart.update()
|
||||
}
|
||||
79
static/scripts/accuracy.js
Normal file
79
static/scripts/accuracy.js
Normal file
@ -0,0 +1,79 @@
|
||||
/**
|
||||
* This file defines an horizontal bar chart used in the live tracking page, showing Ublox horizontal accuracy,
|
||||
* smartphone horizontal accuracy and distance between the positions of the Ublox
|
||||
* and the Smartphone at a same time in meters.
|
||||
*
|
||||
* @authors Timo Volkmann, Frank Herkommer.
|
||||
*/
|
||||
|
||||
//Defines the chart and its properties.
|
||||
let ctx = document.getElementById("accuracy").getContext('2d');
|
||||
let barChart = new Chart(ctx, {
|
||||
type: 'horizontalBar',
|
||||
data: {
|
||||
labels: ["Meters"],
|
||||
datasets: [{
|
||||
label: 'Ublox H. acc.',
|
||||
data: [0, 0],
|
||||
backgroundColor: "rgba(214, 69, 65, 1)"
|
||||
}, {
|
||||
label: 'Smartphone H. acc.',
|
||||
data: [0, 0],
|
||||
backgroundColor: "rgba(30, 139, 195, 1)"
|
||||
}, {
|
||||
label: 'Dist. Ublox-Smartphone',
|
||||
data: [0],
|
||||
backgroundColor: "rgba(30, 139, 0, 1)"
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
scales: {
|
||||
xAxes: [{
|
||||
ticks: {
|
||||
min: 0,
|
||||
max: 10
|
||||
}
|
||||
}]
|
||||
},
|
||||
legend: {
|
||||
display: true,
|
||||
enabled: true
|
||||
},
|
||||
tooltips: {
|
||||
enabled: false,
|
||||
display: false
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Function to add the Horizontal and Vertical accuracy sent by the Ublox to the chart.
|
||||
* Called every time a message is received over serial connection from the server.
|
||||
* @param hacc horizontal accuracy in meters.
|
||||
* @param vacc vertical accuracy in meters
|
||||
*/
|
||||
function addSerialAccuracy(hacc, vacc){
|
||||
barChart.data.datasets[0].data = [hacc, vacc];
|
||||
barChart.update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to add the Horizontal and Vertical accuracy sent by the Smartphone to the chart.
|
||||
* Called every time a message is received over tcp connection from the server.
|
||||
* @param hacc horizontal accuracy in meters.
|
||||
* @param vacc vertical accuracy in meters
|
||||
*/
|
||||
function addTCPAccuracy(hacc, vacc){
|
||||
barChart.data.datasets[1].data = [hacc, vacc];
|
||||
barChart.update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to add the calculated distance between coordinates sent by the Ublox and the coordinates
|
||||
* sent by the smartphone to the chart.
|
||||
* @param dist distance calculated in meters.
|
||||
*/
|
||||
function addDistanceToBarChart(dist){
|
||||
barChart.data.datasets[2].data = [dist];
|
||||
barChart.update();
|
||||
}
|
||||
@ -1,43 +0,0 @@
|
||||
var ctx = document.getElementById('myChart').getContext('2d');
|
||||
var myChart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: new Array(GRAPH_RES),
|
||||
datasets: [{
|
||||
label: 'Z',
|
||||
backgroundColor: 'rgba(255, 99, 132, 0.2)',
|
||||
borderColor: 'rgba(255, 99, 132, 1)',
|
||||
borderWidth: 1,
|
||||
pointRadius: 0,
|
||||
lineTension: 0.5,
|
||||
data: new Array(GRAPH_RES)
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
scales: {
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
// beginAtZero: true
|
||||
min: -100,
|
||||
max: 100
|
||||
}
|
||||
}]
|
||||
},
|
||||
animation: {
|
||||
duration: 0
|
||||
}
|
||||
}
|
||||
});
|
||||
myChart.data.labels.fill("", 0, GRAPH_RES);
|
||||
myChart.data.datasets.forEach((dataset) => dataset.data.fill(0, 0, GRAPH_RES))
|
||||
function addData(data) {
|
||||
myChart.data.labels.push("");
|
||||
myChart.data.datasets.forEach((dataset) => {
|
||||
dataset.data.push(data);
|
||||
});
|
||||
while (myChart.data.labels.length >= GRAPH_RES) {
|
||||
myChart.data.labels.shift();
|
||||
myChart.data.datasets.forEach((dataset) => dataset.data.shift())
|
||||
}
|
||||
myChart.update();
|
||||
};
|
||||
78
static/scripts/distanceCalc.js
Normal file
78
static/scripts/distanceCalc.js
Normal file
@ -0,0 +1,78 @@
|
||||
/**
|
||||
* Function to calculate distance between two coordinates using the haversine algorithm (less precise).
|
||||
* @param coord1 first set of coordinates.
|
||||
* @param coord2 second set of coordinates.
|
||||
* @returns {number} distance between the two points in meters.
|
||||
*/
|
||||
function distanceInMetersBetweenEarthCoordinates(coord1, coord2) {
|
||||
let long1 = coord1[0]
|
||||
let lat1 = coord1[1]
|
||||
let long2 = coord2[0]
|
||||
let lat2 = coord2[1]
|
||||
|
||||
let earthRadiusM = 6371000
|
||||
|
||||
let phi1 = lat1 * Math.PI / 180
|
||||
let phi2 = lat2 * Math.PI / 180
|
||||
|
||||
let dlat = (lat2-lat1) * Math.PI / 180
|
||||
let dlong = (long2 - long1) * Math.PI / 180
|
||||
|
||||
let a = Math.sin(dlat/2) * Math.sin(dlat/2) +
|
||||
Math.cos(phi1) * Math.cos(phi2) *
|
||||
Math.sin(dlong/2) * Math.sin(dlong/2)
|
||||
let c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a))
|
||||
return earthRadiusM * c
|
||||
}
|
||||
|
||||
|
||||
Number.prototype.toRad = function () { return this * Math.PI / 180; }
|
||||
|
||||
/**
|
||||
* Function to calculate distance between two coordinates using the vincenty algorithm (more precise).
|
||||
* @param coord1 first set of coordinates.
|
||||
* @param coord2 second set of coordinates.
|
||||
* @returns {string|number} distance between the two point is meters.
|
||||
*/
|
||||
function distVincenty(coord1, coord2) {
|
||||
const lon1 = coord1[0]
|
||||
const lat1 = coord1[1]
|
||||
const lon2 = coord2[0]
|
||||
const lat2 = coord2[1]
|
||||
var a = 6378137, b = 6356752.314245, f = 1/298.257223563; // WGS-84 ellipsoid params
|
||||
var L = (lon2-lon1).toRad()
|
||||
var U1 = Math.atan((1-f) * Math.tan(lat1.toRad()));
|
||||
var U2 = Math.atan((1-f) * Math.tan(lat2.toRad()));
|
||||
var sinU1 = Math.sin(U1), cosU1 = Math.cos(U1);
|
||||
var sinU2 = Math.sin(U2), cosU2 = Math.cos(U2);
|
||||
|
||||
var lambda = L, lambdaP, iterLimit = 100;
|
||||
do {
|
||||
var sinLambda = Math.sin(lambda), cosLambda = Math.cos(lambda);
|
||||
var sinSigma = Math.sqrt((cosU2*sinLambda) * (cosU2*sinLambda) +
|
||||
(cosU1*sinU2-sinU1*cosU2*cosLambda) * (cosU1*sinU2-sinU1*cosU2*cosLambda));
|
||||
if (sinSigma===0) return 0; // co-incident points
|
||||
var cosSigma = sinU1*sinU2 + cosU1*cosU2*cosLambda;
|
||||
var sigma = Math.atan2(sinSigma, cosSigma);
|
||||
var sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma;
|
||||
var cosSqAlpha = 1 - sinAlpha*sinAlpha;
|
||||
var cos2SigmaM = cosSigma - 2*sinU1*sinU2/cosSqAlpha;
|
||||
if (isNaN(cos2SigmaM)) cos2SigmaM = 0; // equatorial line: cosSqAlpha=0 (§6)
|
||||
var C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));
|
||||
lambdaP = lambda;
|
||||
lambda = L + (1-C) * f * sinAlpha *
|
||||
(sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));
|
||||
} while (Math.abs(lambda-lambdaP) > 1e-12 && --iterLimit>0);
|
||||
|
||||
if (iterLimit===0) return NaN // formula failed to converge
|
||||
|
||||
var uSq = cosSqAlpha * (a*a - b*b) / (b*b);
|
||||
var A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));
|
||||
var B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)));
|
||||
var deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
|
||||
B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));
|
||||
var s = b*A*(sigma-deltaSigma);
|
||||
|
||||
s = s.toFixed(3); // round to 1mm precision
|
||||
return s;
|
||||
}
|
||||
@ -1,737 +0,0 @@
|
||||
{
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "LineString",
|
||||
"coordinates": [
|
||||
[
|
||||
9.196275472640991,
|
||||
49.12280972701122
|
||||
],
|
||||
[
|
||||
9.19629693031311,
|
||||
49.122757066649065
|
||||
],
|
||||
[
|
||||
9.196267426013947,
|
||||
49.1227219597099
|
||||
],
|
||||
[
|
||||
9.196237921714783,
|
||||
49.12268685274588
|
||||
],
|
||||
[
|
||||
9.196205735206604,
|
||||
49.122642969005895
|
||||
],
|
||||
[
|
||||
9.196168184280396,
|
||||
49.12259908522708
|
||||
],
|
||||
[
|
||||
9.196090400218964,
|
||||
49.122556956762885
|
||||
],
|
||||
[
|
||||
9.196015298366547,
|
||||
49.12252536039125
|
||||
],
|
||||
[
|
||||
9.195816814899445,
|
||||
49.122421794365344
|
||||
],
|
||||
[
|
||||
9.19578731060028,
|
||||
49.12246041223081
|
||||
],
|
||||
[
|
||||
9.195752441883085,
|
||||
49.122495519355134
|
||||
],
|
||||
[
|
||||
9.195720255374908,
|
||||
49.1225306264546
|
||||
],
|
||||
[
|
||||
9.195685386657715,
|
||||
49.12257099958827
|
||||
],
|
||||
[
|
||||
9.195658564567566,
|
||||
49.122602595930815
|
||||
],
|
||||
[
|
||||
9.195634424686432,
|
||||
49.12263419225324
|
||||
],
|
||||
[
|
||||
9.195604920387268,
|
||||
49.12266052250654
|
||||
],
|
||||
[
|
||||
9.19557273387909,
|
||||
49.12268334204809
|
||||
],
|
||||
[
|
||||
9.195548593997955,
|
||||
49.12271318297122
|
||||
],
|
||||
[
|
||||
9.195532500743866,
|
||||
49.12273951318259
|
||||
],
|
||||
[
|
||||
9.195497632026672,
|
||||
49.12276057734161
|
||||
],
|
||||
[
|
||||
9.19557273387909,
|
||||
49.12281850373281
|
||||
],
|
||||
[
|
||||
9.195524454116821,
|
||||
49.12285712128936
|
||||
],
|
||||
[
|
||||
9.195497632026672,
|
||||
49.12287818539843
|
||||
],
|
||||
[
|
||||
9.195476174354553,
|
||||
49.122904515522194
|
||||
],
|
||||
[
|
||||
9.195586144924162,
|
||||
49.12300983587742
|
||||
],
|
||||
[
|
||||
9.195840954780579,
|
||||
49.1232152099268
|
||||
],
|
||||
[
|
||||
9.19605016708374,
|
||||
49.1233942532759
|
||||
],
|
||||
[
|
||||
9.196152091026306,
|
||||
49.1235346789797
|
||||
],
|
||||
[
|
||||
9.196280837059021,
|
||||
49.12368212554077
|
||||
],
|
||||
[
|
||||
9.196393489837646,
|
||||
49.12382606104651
|
||||
],
|
||||
[
|
||||
9.196511507034302,
|
||||
49.123924358225025
|
||||
],
|
||||
[
|
||||
9.196581244468689,
|
||||
49.12404371882266
|
||||
],
|
||||
[
|
||||
9.196720719337463,
|
||||
49.124173610911306
|
||||
],
|
||||
[
|
||||
9.196838736534119,
|
||||
49.12435967195905
|
||||
],
|
||||
[
|
||||
9.196951389312744,
|
||||
49.124501850213676
|
||||
],
|
||||
[
|
||||
9.197013080120087,
|
||||
49.1245896143649
|
||||
],
|
||||
[
|
||||
9.19705867767334,
|
||||
49.12465280445759
|
||||
],
|
||||
[
|
||||
9.19714719057083,
|
||||
49.12476865275172
|
||||
],
|
||||
[
|
||||
9.197292029857635,
|
||||
49.12495120102961
|
||||
],
|
||||
[
|
||||
9.197361767292023,
|
||||
49.12506529336202
|
||||
],
|
||||
[
|
||||
9.197455644607544,
|
||||
49.125175874910624
|
||||
],
|
||||
[
|
||||
9.197522699832916,
|
||||
49.12529347723932
|
||||
],
|
||||
[
|
||||
9.197605848312378,
|
||||
49.12543565281655
|
||||
],
|
||||
[
|
||||
9.197745323181152,
|
||||
49.125690163634275
|
||||
],
|
||||
[
|
||||
9.197841882705688,
|
||||
49.12584989044582
|
||||
],
|
||||
[
|
||||
9.19790893793106,
|
||||
49.12598328826778
|
||||
],
|
||||
[
|
||||
9.197978675365448,
|
||||
49.12612195141281
|
||||
],
|
||||
[
|
||||
9.198064506053925,
|
||||
49.12627290072483
|
||||
],
|
||||
[
|
||||
9.19819325208664,
|
||||
49.126525652032335
|
||||
],
|
||||
[
|
||||
9.198254942893982,
|
||||
49.12668011053043
|
||||
],
|
||||
[
|
||||
9.198305904865265,
|
||||
49.12679770929164
|
||||
],
|
||||
[
|
||||
9.198405146598816,
|
||||
49.12695743253551
|
||||
],
|
||||
[
|
||||
9.198488295078278,
|
||||
49.12716981099699
|
||||
],
|
||||
[
|
||||
9.198619723320007,
|
||||
49.12720315959838
|
||||
],
|
||||
[
|
||||
9.198799431324005,
|
||||
49.127229487425765
|
||||
],
|
||||
[
|
||||
9.199027419090271,
|
||||
49.12716630061657
|
||||
],
|
||||
[
|
||||
9.19931173324585,
|
||||
49.127129441607394
|
||||
],
|
||||
[
|
||||
9.199504852294922,
|
||||
49.12708556179883
|
||||
],
|
||||
[
|
||||
9.19965773820877,
|
||||
49.12704870272959
|
||||
],
|
||||
[
|
||||
9.199883043766022,
|
||||
49.12700482284956
|
||||
],
|
||||
[
|
||||
9.200116395950317,
|
||||
49.1269732293119
|
||||
],
|
||||
[
|
||||
9.200357794761658,
|
||||
49.12690653177737
|
||||
],
|
||||
[
|
||||
9.200548231601715,
|
||||
49.12688546937944
|
||||
],
|
||||
[
|
||||
9.20065551996231,
|
||||
49.126911797375485
|
||||
],
|
||||
[
|
||||
9.200770854949951,
|
||||
49.12695743253551
|
||||
],
|
||||
[
|
||||
9.200899600982666,
|
||||
49.12702061961085
|
||||
],
|
||||
[
|
||||
9.20103371143341,
|
||||
49.12706800986451
|
||||
],
|
||||
[
|
||||
9.201240241527557,
|
||||
49.12711891045688
|
||||
],
|
||||
[
|
||||
9.20141190290451,
|
||||
49.12714874871086
|
||||
],
|
||||
[
|
||||
9.2015540599823,
|
||||
49.127191750868846
|
||||
],
|
||||
[
|
||||
9.201587587594986,
|
||||
49.127187362895256
|
||||
],
|
||||
[
|
||||
9.201736450195312,
|
||||
49.1271601574503
|
||||
],
|
||||
[
|
||||
9.201810210943222,
|
||||
49.127157524664504
|
||||
],
|
||||
[
|
||||
9.201871901750565,
|
||||
49.12715313668789
|
||||
],
|
||||
[
|
||||
9.201933592557907,
|
||||
49.12710925690026
|
||||
],
|
||||
[
|
||||
9.202055633068085,
|
||||
49.12697498450896
|
||||
],
|
||||
[
|
||||
9.20224204659462,
|
||||
49.12691530777389
|
||||
],
|
||||
[
|
||||
9.20237347483635,
|
||||
49.126887224579605
|
||||
],
|
||||
[
|
||||
9.202480763196945,
|
||||
49.126842466955814
|
||||
],
|
||||
[
|
||||
9.20254647731781,
|
||||
49.12681613892294
|
||||
],
|
||||
[
|
||||
9.202671200037003,
|
||||
49.126769626030736
|
||||
],
|
||||
[
|
||||
9.202869683504105,
|
||||
49.126692396981234
|
||||
],
|
||||
[
|
||||
9.202970266342163,
|
||||
49.12665729282806
|
||||
],
|
||||
[
|
||||
9.203054755926132,
|
||||
49.12662218865002
|
||||
],
|
||||
[
|
||||
9.203156679868698,
|
||||
49.12659147247387
|
||||
],
|
||||
[
|
||||
9.203227758407593,
|
||||
49.126569532336404
|
||||
],
|
||||
[
|
||||
9.203289449214935,
|
||||
49.126551980219446
|
||||
],
|
||||
[
|
||||
9.203341752290726,
|
||||
49.12653179527724
|
||||
],
|
||||
[
|
||||
9.203158020973206,
|
||||
49.126483526903876
|
||||
],
|
||||
[
|
||||
9.203088283538818,
|
||||
49.12646334193381
|
||||
],
|
||||
[
|
||||
9.203002452850342,
|
||||
49.12644140173965
|
||||
],
|
||||
[
|
||||
9.202857613563538,
|
||||
49.12640278697433
|
||||
],
|
||||
[
|
||||
9.202712774276733,
|
||||
49.126357151303814
|
||||
],
|
||||
[
|
||||
9.202632308006287,
|
||||
49.126325557353475
|
||||
],
|
||||
[
|
||||
9.202412366867065,
|
||||
49.12626236939239
|
||||
],
|
||||
[
|
||||
9.202256798744202,
|
||||
49.126213223144774
|
||||
],
|
||||
[
|
||||
9.202122688293455,
|
||||
49.12616758729978
|
||||
],
|
||||
[
|
||||
9.201961755752563,
|
||||
49.12612546186714
|
||||
],
|
||||
[
|
||||
9.2018061876297,
|
||||
49.12607982594142
|
||||
],
|
||||
[
|
||||
9.201698899269104,
|
||||
49.126037700434225
|
||||
],
|
||||
[
|
||||
9.201596975326538,
|
||||
49.125999085354515
|
||||
],
|
||||
[
|
||||
9.20129120349884,
|
||||
49.125883239934964
|
||||
],
|
||||
[
|
||||
9.201119542121887,
|
||||
49.125827072361396
|
||||
],
|
||||
[
|
||||
9.200921058654785,
|
||||
49.12578143616102
|
||||
],
|
||||
[
|
||||
9.200685024261473,
|
||||
49.125676121692166
|
||||
],
|
||||
[
|
||||
9.200513362884521,
|
||||
49.12560591192202
|
||||
],
|
||||
[
|
||||
9.200336337089539,
|
||||
49.12554623353922
|
||||
],
|
||||
[
|
||||
9.199842810630798,
|
||||
49.125360176943595
|
||||
],
|
||||
[
|
||||
9.199681878089905,
|
||||
49.12527592467067
|
||||
],
|
||||
[
|
||||
9.1995370388031,
|
||||
49.12522677744532
|
||||
],
|
||||
[
|
||||
9.199456572532654,
|
||||
49.12518816173411
|
||||
],
|
||||
[
|
||||
9.19932246208191,
|
||||
49.12513199337321
|
||||
],
|
||||
[
|
||||
9.199220538139343,
|
||||
49.12508635653314
|
||||
],
|
||||
[
|
||||
9.199113249778748,
|
||||
49.125023166992925
|
||||
],
|
||||
[
|
||||
9.199016690254211,
|
||||
49.12496699844514
|
||||
],
|
||||
[
|
||||
9.198925495147705,
|
||||
49.1248932771296
|
||||
],
|
||||
[
|
||||
9.198732376098633,
|
||||
49.12480551351584
|
||||
],
|
||||
[
|
||||
9.198582172393799,
|
||||
49.124721260300475
|
||||
],
|
||||
[
|
||||
9.198474884033203,
|
||||
49.124647538619605
|
||||
],
|
||||
[
|
||||
9.198367595672607,
|
||||
49.12459839077146
|
||||
],
|
||||
[
|
||||
9.198265671730042,
|
||||
49.12455626400573
|
||||
],
|
||||
[
|
||||
9.198126196861267,
|
||||
49.124542221742516
|
||||
],
|
||||
[
|
||||
9.198099374771118,
|
||||
49.12450360549822
|
||||
],
|
||||
[
|
||||
9.198126196861267,
|
||||
49.12441584119478
|
||||
],
|
||||
[
|
||||
9.198174476623533,
|
||||
49.12433509789843
|
||||
],
|
||||
[
|
||||
9.19828176498413,
|
||||
49.12430701324279
|
||||
],
|
||||
[
|
||||
9.19831931591034,
|
||||
49.12427190740087
|
||||
],
|
||||
[
|
||||
9.198254942893982,
|
||||
49.12420871682283
|
||||
],
|
||||
[
|
||||
9.198115468025208,
|
||||
49.124149036758475
|
||||
],
|
||||
[
|
||||
9.197981357574463,
|
||||
49.124085846023824
|
||||
],
|
||||
[
|
||||
9.197836518287659,
|
||||
49.124026165811614
|
||||
],
|
||||
[
|
||||
9.197707772254944,
|
||||
49.12395595370529
|
||||
],
|
||||
[
|
||||
9.197557568550108,
|
||||
49.12386467781845
|
||||
],
|
||||
[
|
||||
9.197487831115723,
|
||||
49.12381201857656
|
||||
],
|
||||
[
|
||||
9.197385907173157,
|
||||
49.123717231800214
|
||||
],
|
||||
[
|
||||
9.197214245796204,
|
||||
49.12367510428589
|
||||
],
|
||||
[
|
||||
9.197010397911072,
|
||||
49.123566274708274
|
||||
],
|
||||
[
|
||||
9.196908473968506,
|
||||
49.123474998104186
|
||||
],
|
||||
[
|
||||
9.196704626083374,
|
||||
49.123401274570526
|
||||
],
|
||||
[
|
||||
9.196602702140808,
|
||||
49.123348614836544
|
||||
],
|
||||
[
|
||||
9.196484684944153,
|
||||
49.123260848488954
|
||||
],
|
||||
[
|
||||
9.196339845657349,
|
||||
49.12319414596088
|
||||
],
|
||||
[
|
||||
9.196216464042664,
|
||||
49.12313095400942
|
||||
],
|
||||
[
|
||||
9.196135997772217,
|
||||
49.12306776197748
|
||||
],
|
||||
[
|
||||
9.19607162475586,
|
||||
49.12299754851418
|
||||
],
|
||||
[
|
||||
9.195937514305115,
|
||||
49.12295893106699
|
||||
],
|
||||
[
|
||||
9.195835590362549,
|
||||
49.12289222813283
|
||||
],
|
||||
[
|
||||
9.195733666419983,
|
||||
49.12282903579667
|
||||
],
|
||||
[
|
||||
9.195638447999954,
|
||||
49.122754433629495
|
||||
],
|
||||
[
|
||||
9.195600226521492,
|
||||
49.12273293063105
|
||||
],
|
||||
[
|
||||
9.195574074983597,
|
||||
49.122708355764296
|
||||
],
|
||||
[
|
||||
9.195574074983597,
|
||||
49.12269431297779
|
||||
],
|
||||
[
|
||||
9.195623695850372,
|
||||
49.1226412136555
|
||||
],
|
||||
[
|
||||
9.195666611194609,
|
||||
49.12260961733753
|
||||
],
|
||||
[
|
||||
9.195688739418983,
|
||||
49.12258021519025
|
||||
],
|
||||
[
|
||||
9.195733666419983,
|
||||
49.12253106529318
|
||||
],
|
||||
[
|
||||
9.19575646519661,
|
||||
49.12250034658276
|
||||
],
|
||||
[
|
||||
9.195783287286758,
|
||||
49.12247269972715
|
||||
],
|
||||
[
|
||||
9.195801392197609,
|
||||
49.12244988008865
|
||||
],
|
||||
[
|
||||
9.195815473794937,
|
||||
49.122438470265486
|
||||
],
|
||||
[
|
||||
9.195830225944519,
|
||||
49.12242047784666
|
||||
],
|
||||
[
|
||||
9.195859730243683,
|
||||
49.122431887674
|
||||
],
|
||||
[
|
||||
9.195901304483414,
|
||||
49.122448563570735
|
||||
],
|
||||
[
|
||||
9.195931479334831,
|
||||
49.12246787249679
|
||||
],
|
||||
[
|
||||
9.195965006947517,
|
||||
49.12248367070343
|
||||
],
|
||||
[
|
||||
9.195998534560204,
|
||||
49.122498152388445
|
||||
],
|
||||
[
|
||||
9.19603407382965,
|
||||
49.12251307290797
|
||||
],
|
||||
[
|
||||
9.196063578128815,
|
||||
49.12253501484029
|
||||
],
|
||||
[
|
||||
9.196093752980232,
|
||||
49.122546424641236
|
||||
],
|
||||
[
|
||||
9.196127280592918,
|
||||
49.1225600286313
|
||||
],
|
||||
[
|
||||
9.19615812599659,
|
||||
49.12258109286655
|
||||
],
|
||||
[
|
||||
9.196201711893082,
|
||||
49.12261927177015
|
||||
],
|
||||
[
|
||||
9.196238592267036,
|
||||
49.12267237111598
|
||||
],
|
||||
[
|
||||
9.196262061595917,
|
||||
49.12270045669739
|
||||
],
|
||||
[
|
||||
9.196281507611275,
|
||||
49.122722837383684
|
||||
],
|
||||
[
|
||||
9.196305647492409,
|
||||
49.122746534569934
|
||||
],
|
||||
[
|
||||
9.196302965283394,
|
||||
49.1227693540719
|
||||
],
|
||||
[
|
||||
9.196292236447334,
|
||||
49.12279392890845
|
||||
],
|
||||
[
|
||||
9.196286201477049,
|
||||
49.122811482355665
|
||||
],
|
||||
[
|
||||
9.19628955423832,
|
||||
49.12282815812477
|
||||
],
|
||||
[
|
||||
9.196309000253677,
|
||||
49.1228479057388
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
211
static/scripts/indicators.js
Normal file
211
static/scripts/indicators.js
Normal file
@ -0,0 +1,211 @@
|
||||
let width = document.getElementById("viewport").offsetWidth
|
||||
let height = 300;
|
||||
|
||||
let renderer = new THREE.WebGLRenderer({ antialias: true });
|
||||
renderer.setSize(width, height);
|
||||
document.getElementById("viewport").appendChild(renderer.domElement);
|
||||
|
||||
let scene = new THREE.Scene();
|
||||
|
||||
let cubeGeometry = new THREE.CubeGeometry(100, 100/2, 100*1.5);
|
||||
let cubeGeometry2 = new THREE.CubeGeometry(120, 120/2, 120*1.5);
|
||||
|
||||
const color = new THREE.Color("rgb(255, 0, 0)");
|
||||
let cubeMaterial = new THREE.MeshPhongMaterial({
|
||||
color: color,
|
||||
opacity: 1,
|
||||
transparent: true,
|
||||
});
|
||||
const color2 = new THREE.Color("rgb(48,117,255)");
|
||||
let cubeMaterial2 = new THREE.MeshPhongMaterial({
|
||||
color: color2,
|
||||
opacity: 0.5,
|
||||
transparent: true,
|
||||
});
|
||||
let cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
|
||||
let cube2 = new THREE.Mesh(cubeGeometry2, cubeMaterial2);
|
||||
scene.add(cube);
|
||||
scene.add(cube2);
|
||||
|
||||
let camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 6000);
|
||||
camera.position.y = 100;
|
||||
camera.position.z = 240;
|
||||
camera.lookAt(cube.position);
|
||||
|
||||
scene.add(camera);
|
||||
|
||||
let skyboxGeometry = new THREE.CubeGeometry(5000, 5000, 5000);
|
||||
let skyboxMaterial = new THREE.MeshBasicMaterial({ color: 0x232323, side: THREE.BackSide });
|
||||
let skybox = new THREE.Mesh(skyboxGeometry, skyboxMaterial);
|
||||
|
||||
scene.add(skybox);
|
||||
|
||||
const colorl = 0xFFFFFF;
|
||||
const intensity = 1;
|
||||
const light = new THREE.DirectionalLight(colorl, intensity);
|
||||
|
||||
let pointLight = new THREE.PointLight(0xffffff);
|
||||
pointLight.position.set(0, 300, 200);
|
||||
light.position.set(0, 300, 200);
|
||||
|
||||
scene.add(pointLight);
|
||||
|
||||
cube.position.x = 0
|
||||
cube2.position.x = 0
|
||||
|
||||
|
||||
|
||||
// calibration globals
|
||||
let manCalibration = new THREE.Euler( 0, 0, 0, 'XYZ' )
|
||||
let calibrationRot = new THREE.Quaternion()
|
||||
let calPitch = 0
|
||||
let calRoll = 0
|
||||
let calYaw = 0
|
||||
|
||||
let quaternionOffset = document.getElementById("quaternionOffset")
|
||||
|
||||
// function to set current cube rotation from sensor data with respect to calibration
|
||||
function renderTCP(x, y, z) {
|
||||
let calibration = new THREE.Quaternion().setFromEuler(manCalibration)
|
||||
let eul = new THREE.Euler( x, y, z, 'YXZ' );
|
||||
|
||||
cube2.quaternion.setFromEuler(eul).multiply(calibrationRot).multiply(calibration)
|
||||
|
||||
quaternionOffset.innerHTML = `Lage Abweichung: ${(cube2.quaternion.angleTo(cube.quaternion) * 180 / Math.PI).toFixed(2) }°`
|
||||
|
||||
renderer.render(scene, camera);
|
||||
}
|
||||
|
||||
// function to set current cube rotation from sensor data
|
||||
function renderSerial(x, y, z) {
|
||||
let eul = new THREE.Euler( x, y, z, 'YXZ' ); // XYZ XZY YZX YXZ ZXY ZYX
|
||||
|
||||
cube.quaternion.setFromEuler(eul)
|
||||
|
||||
renderer.render(scene, camera);
|
||||
}
|
||||
|
||||
renderTCP(0, 0, 0);
|
||||
renderSerial(0, 0, 0);
|
||||
|
||||
let pitchRange = document.getElementById("pitchRange");
|
||||
let yawRange = document.getElementById("yawRange");
|
||||
let rollRange = document.getElementById("rollRange");
|
||||
|
||||
pitchRange.oninput = () => {
|
||||
manCalibration.x = pitchRange.value * Math.PI / 180
|
||||
}
|
||||
yawRange.oninput = () => {
|
||||
manCalibration.y = yawRange.value * Math.PI / 180
|
||||
}
|
||||
rollRange.oninput = () => {
|
||||
manCalibration.z = rollRange.value * Math.PI / 180
|
||||
}
|
||||
|
||||
function delCalibration(evt) {
|
||||
calibrationRot = new THREE.Quaternion()
|
||||
manCalibration = new THREE.Euler( 0, 0, 0, 'XYZ' )
|
||||
pitchRange.value = 0
|
||||
yawRange.value = 0
|
||||
rollRange.value = 0
|
||||
calRoll = 0
|
||||
calPitch = 0
|
||||
}
|
||||
|
||||
let calState = false;
|
||||
function manualCalibration(evt) {
|
||||
let con = document.getElementById("manCalContainer")
|
||||
console.log("mancal", con.style.display)
|
||||
if (calState === false) {
|
||||
delCalibration()
|
||||
calState = !calState
|
||||
console.log("mancal ON")
|
||||
con.style.display = "block"
|
||||
} else {
|
||||
delCalibration()
|
||||
calState = !calState
|
||||
console.log("mancal OFF")
|
||||
con.style.display = "none"
|
||||
manCalibration = new THREE.Euler( 0, 0, 0, 'XYZ' )
|
||||
pitchRange.value = 0
|
||||
yawRange.value = 0
|
||||
rollRange.value = 0
|
||||
}
|
||||
}
|
||||
function calibrate(evt) {
|
||||
let serOrientation = cube.quaternion.clone()
|
||||
let tcpOrientation = cube2.quaternion.clone().multiply(calibrationRot.clone().invert())
|
||||
let diff = tcpOrientation.invert().multiply(serOrientation)
|
||||
|
||||
let old = new THREE.Euler().setFromQuaternion( cube2.quaternion, 'YXZ' )
|
||||
let dif = new THREE.Euler().setFromQuaternion( diff )
|
||||
console.log("OLD:","pitch", old.x * 180/Math.PI, "yaw", old.y * 180/Math.PI, "roll", old.z * 180/Math.PI)
|
||||
console.log("DIFF:","pitch", dif.x * 180/Math.PI, "yaw", dif.y * 180/Math.PI, "roll", dif.z * 180/Math.PI)
|
||||
calPitch = dif.x
|
||||
calYaw = dif.y
|
||||
calRoll = dif.z
|
||||
calibrationRot = diff
|
||||
}
|
||||
document.getElementById("deleteCalibration").onclick = delCalibration
|
||||
document.getElementById("manualCalibration").onclick = manualCalibration
|
||||
document.getElementById("calibrate").onclick = calibrate
|
||||
|
||||
|
||||
// indicators from https://github.com/sebmatton/jQuery-Flight-Indicators.git
|
||||
|
||||
let options = {
|
||||
size : 200, // Sets the size in pixels of the indicator (square)
|
||||
roll : 0, // Roll angle in degrees for an attitude indicator
|
||||
pitch : 0, // Pitch angle in degrees for an attitude indicator
|
||||
heading: 0, // Heading angle in degrees for an heading indicator
|
||||
vario: 0, // Variometer in 1000 feets/min for the variometer indicator
|
||||
airspeed: 0, // Air speed in knots for an air speed indicator
|
||||
altitude: 0, // Altitude in feets for an altimeter indicator
|
||||
pressure: 1000, // Pressure in hPa for an altimeter indicator
|
||||
showBox : true, // Sets if the outer squared box is visible or not (true or false)
|
||||
img_directory : 'static/indicators/img/' // The directory where the images are saved to
|
||||
}
|
||||
|
||||
let headingSer = $.flightIndicator('#headingSer', 'heading', options);
|
||||
let headingTcp = $.flightIndicator('#headingTcp', 'heading', options);
|
||||
let attitudeSer = $.flightIndicator('#attitudeSer', 'attitude', options);
|
||||
let attitudeTcp = $.flightIndicator('#attitudeTcp', 'attitude', options);
|
||||
let airspeed = $.flightIndicator('#airspeed', 'airspeed', options);
|
||||
let altimeter = $.flightIndicator('#altimeter', 'altimeter', options);
|
||||
|
||||
let airspeedLabel = document.getElementById("airspeedLabel")
|
||||
let altitudeLabel = document.getElementById("altitudeLabel")
|
||||
|
||||
// function to set analog indictors from current sensor data
|
||||
function setIndicatorsTcp(sensordata) {
|
||||
let q = new THREE.Euler().setFromQuaternion( cube2.quaternion, 'YXZ' ) // XYZ XZY YZX YXZ ZXY ZYX
|
||||
|
||||
if (sensordata.Orientation[0] !== 0 && sensordata.Orientation[1] !== 0) {
|
||||
attitudeTcp.setPitch(q.x * 180 / Math.PI)
|
||||
attitudeTcp.setRoll(q.z * 180 / Math.PI)
|
||||
}
|
||||
let heading = sensordata.HeadDevice
|
||||
if (heading !== 0) {
|
||||
headingTcp.setHeading(heading)
|
||||
}
|
||||
}
|
||||
|
||||
// function to set analog indictors from current sensor data
|
||||
function setIndicatorsSer(sensordata) {
|
||||
if (sensordata.Orientation[0] !== 0 && sensordata.Orientation[1] !== 0) {
|
||||
attitudeSer.setPitch(sensordata.Orientation[0])
|
||||
attitudeSer.setRoll(sensordata.Orientation[1])
|
||||
}
|
||||
let heading = sensordata.HeadMotion
|
||||
if (heading !== 0) {
|
||||
headingSer.setHeading(heading)
|
||||
}
|
||||
if (sensordata.Speed !== 0) {
|
||||
airspeed.setAirSpeed(sensordata.Speed * 3.6)
|
||||
airspeedLabel.innerHTML = `Ref. Speed: ${(sensordata.Speed * 3.6).toFixed(1)} km/h`
|
||||
}
|
||||
if (sensordata.Position[2] !== 0) {
|
||||
altimeter.setAltitude((sensordata.Position[2] * 10).toFixed())
|
||||
altitudeLabel.innerHTML = `HMSL: ${(sensordata.Position[2]).toFixed(2)} m`
|
||||
}
|
||||
}
|
||||
@ -1,22 +1,30 @@
|
||||
/**
|
||||
* This file defines the map in satellite style for the live tracking page, defines and updates its data sources.
|
||||
*
|
||||
* @authors Timo Volkmann, Frank Herkommer.
|
||||
*/
|
||||
|
||||
mapboxgl.accessToken = 'pk.eyJ1IjoiZmhlcmtvbW0iLCJhIjoiY2tobm81bXppMGVuNzMyazY3eDU0M2dyaSJ9.qWJrwtv7KitW60pzs6h3Gg';
|
||||
var map = new mapboxgl.Map({
|
||||
let map = new mapboxgl.Map({
|
||||
container: 'map',
|
||||
style: 'mapbox://styles/mapbox/streets-v11',
|
||||
style: 'mapbox://styles/mapbox/satellite-v9',
|
||||
zoom: 0
|
||||
});
|
||||
var emptyTCP = {
|
||||
type: "FeatureCollection",
|
||||
features: [
|
||||
{
|
||||
type: "Feature",
|
||||
geometry: {
|
||||
type: "LineString",
|
||||
coordinates: []
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
var emptySERIAL = {
|
||||
|
||||
//Empty geoJSON for coordinates from TCP input
|
||||
let emptyTCP = {
|
||||
type: "FeatureCollection",
|
||||
features: [
|
||||
{
|
||||
type: "Feature",
|
||||
geometry: {
|
||||
type: "LineString",
|
||||
coordinates: []
|
||||
}
|
||||
}]
|
||||
}
|
||||
//Empty geoJSON for coordinates from serial input
|
||||
let emptySERIAL = {
|
||||
type: "FeatureCollection",
|
||||
features: [
|
||||
{
|
||||
@ -28,15 +36,10 @@ var emptySERIAL = {
|
||||
}]
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the map with its data sources and its different layers.
|
||||
*/
|
||||
map.on('load', function () {
|
||||
// save full coordinate list for later
|
||||
//var coordinates = data.features[0].geometry.coordinates;
|
||||
|
||||
// start by showing just the first coordinate
|
||||
//data.features[0].geometry.coordinates = [coordinates[0]];
|
||||
|
||||
// add it to the map
|
||||
//map.addSource('trace', { type: 'geojson', data: data });
|
||||
|
||||
map.addSource('routeTCP', { 'type': 'geojson', 'data': emptyTCP })
|
||||
map.addSource('routeSERIAL', { 'type': 'geojson', 'data': emptySERIAL })
|
||||
@ -49,8 +52,8 @@ map.on('load', function () {
|
||||
'visibility': 'visible'
|
||||
},
|
||||
'paint': {
|
||||
'line-color': 'blue',
|
||||
'line-opacity': 0.75,
|
||||
'line-color': 'rgba(30, 139, 195, 1)',
|
||||
'line-opacity': 1,
|
||||
'line-width': 5
|
||||
}
|
||||
});
|
||||
@ -63,28 +66,42 @@ map.on('load', function () {
|
||||
'visibility': 'visible'
|
||||
},
|
||||
'paint': {
|
||||
'line-color': 'yellow',
|
||||
'line-opacity': 0.75,
|
||||
'line-color': 'rgba(214, 69, 65, 1)',
|
||||
'line-opacity': 1,
|
||||
'line-width': 5
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
map.jumpTo({ 'center': [9.19640999, 49.12283027], 'zoom': 17 });
|
||||
map.jumpTo({ 'center': [9.19640999, 49.12283027], 'zoom': 16 });
|
||||
map.setPitch(30);
|
||||
|
||||
var stateLegendEl = document.getElementById('state-legend');
|
||||
let stateLegendEl = document.getElementById('state-legend');
|
||||
stateLegendEl.style.display = 'block';
|
||||
})
|
||||
|
||||
function updateMapTCP (long, lat) {
|
||||
emptyTCP.features[0].geometry.coordinates.push([long, lat]);
|
||||
/**
|
||||
* Function to push coordinates data coming from a TCP connection
|
||||
* into the emptyTCP geoJSON object.
|
||||
* Called every time a message is received over TCP from the server.
|
||||
*
|
||||
* @param TCPlong longitude coming in from device connected over TCP port.
|
||||
* @param TCPlat latitude coming in from device connected over TCP port.
|
||||
*/
|
||||
function updateMapTCP (TCPlong, TCPlat) {
|
||||
emptyTCP.features[0].geometry.coordinates.push([TCPlong, TCPlat]);
|
||||
map.getSource('routeTCP').setData(emptyTCP);
|
||||
map.panTo([long, lat]);
|
||||
}
|
||||
|
||||
function updateMapSERIAL (long, lat) {
|
||||
emptySERIAL.features[0].geometry.coordinates.push([long, lat]);
|
||||
/**
|
||||
* Function to push coordinates data coming from a serial connection
|
||||
* into the emptySERIAL geoJSON object.
|
||||
* Called every time a message is received over serial connection from the server.
|
||||
*
|
||||
* @param SERIALlong longitude coming in from device connected over serial port.
|
||||
* @param SERIALlat latitude coming in from device connected over serial port.
|
||||
*/
|
||||
function updateMapSERIAL (SERIALlong, SERIALlat) {
|
||||
emptySERIAL.features[0].geometry.coordinates.push([SERIALlong, SERIALlat]);
|
||||
map.getSource('routeSERIAL').setData(emptySERIAL);
|
||||
//map.panTo([long, lat]);
|
||||
}
|
||||
}
|
||||
|
||||
116
static/scripts/mapfull.js
Normal file
116
static/scripts/mapfull.js
Normal file
@ -0,0 +1,116 @@
|
||||
/**
|
||||
* This file defines the map in satellite style for the full replay page.
|
||||
*
|
||||
* @authors Timo Volkmann, Frank Herkommer.
|
||||
*/
|
||||
|
||||
mapboxgl.accessToken = 'pk.eyJ1IjoiZmhlcmtvbW0iLCJhIjoiY2tobm81bXppMGVuNzMyazY3eDU0M2dyaSJ9.qWJrwtv7KitW60pzs6h3Gg';
|
||||
let map = new mapboxgl.Map({
|
||||
container: 'map',
|
||||
style: 'mapbox://styles/mapbox/satellite-v9',
|
||||
zoom: 0
|
||||
});
|
||||
|
||||
/**
|
||||
* Set up the map with its data sources and its different layers.
|
||||
*/
|
||||
map.on('load', function () {
|
||||
|
||||
map.addSource('routeTCP', { 'type': 'geojson', 'data': null })
|
||||
map.addSource('routeSERIAL', { 'type': 'geojson', 'data': null })
|
||||
|
||||
map.addLayer({
|
||||
'id': 'routeTCP',
|
||||
'type': 'line',
|
||||
'source': 'routeTCP',
|
||||
'layout': {
|
||||
'visibility': 'visible'
|
||||
},
|
||||
'paint': {
|
||||
'line-color': 'rgba(30, 139, 195, 1)',
|
||||
'line-opacity': 1,
|
||||
'line-width': 5
|
||||
}
|
||||
});
|
||||
|
||||
map.addLayer({
|
||||
'id': 'routeSERIAL',
|
||||
'type': 'line',
|
||||
'source': 'routeSERIAL',
|
||||
'layout': {
|
||||
'visibility': 'visible'
|
||||
},
|
||||
'paint': {
|
||||
'line-color': 'rgba(214, 69, 65, 1)',
|
||||
'line-opacity': 1,
|
||||
'line-width': 5
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
map.jumpTo({ 'center': [9.19640999, 49.12283027], 'zoom': 16 });
|
||||
map.setPitch(30);
|
||||
|
||||
let stateLegendEl = document.getElementById('state-legend');
|
||||
stateLegendEl.style.display = 'block';
|
||||
})
|
||||
|
||||
/**
|
||||
* Function to add all collected coordinates sent in by the Smartphone to the map.
|
||||
* @param sensordataList List of all received messages of the tcp source and their sensor data
|
||||
*/
|
||||
function updateMapTCPbulk(sensordataList) {
|
||||
console.log("add TCP data to map")
|
||||
let geoJsonTCP = {
|
||||
type: "FeatureCollection",
|
||||
features: [
|
||||
{
|
||||
type: "Feature",
|
||||
geometry: {
|
||||
type: "LineString",
|
||||
coordinates: []
|
||||
}
|
||||
}]
|
||||
}
|
||||
sensordataList.forEach(sensordata => {
|
||||
if (sensordata.Position[0] === 0 && sensordata.Position[1] === 0 && sensordata.Position[2] === 0) {
|
||||
return;
|
||||
}
|
||||
let lat = sensordata.Position[0]
|
||||
let lon = sensordata.Position[1]
|
||||
geoJsonTCP.features[0].geometry.coordinates.push([lon, lat]);
|
||||
|
||||
})
|
||||
map.getSource('routeTCP').setData(geoJsonTCP);
|
||||
map.panTo(geoJsonTCP.features[0].geometry.coordinates[geoJsonTCP.features[0].geometry.coordinates.length-1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to add all collected coordinates sent in by the Ublox to the map.
|
||||
* @param sensordataList List of all received messages of the serial source and their sensor data
|
||||
*/
|
||||
function updateMapSERIALbulk(sensordataList) {
|
||||
console.log("add SERIAL data to map")
|
||||
let geoJsonSerial = {
|
||||
type: "FeatureCollection",
|
||||
features: [
|
||||
{
|
||||
type: "Feature",
|
||||
geometry: {
|
||||
type: "LineString",
|
||||
coordinates: []
|
||||
}
|
||||
}]
|
||||
}
|
||||
sensordataList.forEach(sensordata => {
|
||||
if (sensordata.Position[0] === 0 && sensordata.Position[1] === 0 && sensordata.Position[2] === 0) {
|
||||
return;
|
||||
}
|
||||
let lat = sensordata.Position[0]
|
||||
let lon = sensordata.Position[1]
|
||||
geoJsonSerial.features[0].geometry.coordinates.push([lon, lat]);
|
||||
|
||||
})
|
||||
map.getSource('routeSERIAL').setData(geoJsonSerial);
|
||||
map.panTo(geoJsonSerial.features[0].geometry.coordinates[geoJsonSerial.features[0].geometry.coordinates.length-1]);
|
||||
}
|
||||
188
static/scripts/refull.js
Normal file
188
static/scripts/refull.js
Normal file
@ -0,0 +1,188 @@
|
||||
/**
|
||||
* This file contains all the controls for the full replay page.
|
||||
*
|
||||
* @authors Timo Volkmann, Frank Herkommer.
|
||||
*/
|
||||
|
||||
// indexes of a list of all collected Serial data where Timestamps matched with the smallest time
|
||||
//difference so they can be fitted on a chart with a smaller amount of tcp data
|
||||
let indexes
|
||||
|
||||
/**
|
||||
* function to parse a timestamp to a number
|
||||
* @param time Timestamp
|
||||
* @returns composed a number
|
||||
*/
|
||||
function composeTimestamp(time){
|
||||
let composed;
|
||||
composed = time.slice(11,25).split(':').join("").split('.').join("");
|
||||
return composed;
|
||||
}
|
||||
|
||||
/**
|
||||
* function to compare a Timestamp from tcp to all timestamps from serial to find a best match.
|
||||
* @param num tcp timestamp
|
||||
* @param arr list of serial timestamps
|
||||
* @returns {(*|number)[]} array with the index of the closest Serial timestamp match
|
||||
*/
|
||||
function findBestTimeMatch(num, arr) {
|
||||
let mid;
|
||||
let lo = 0;
|
||||
let hi = arr.length - 1;
|
||||
while (hi - lo > 1) {
|
||||
mid = Math.floor ((lo + hi) / 2);
|
||||
if (arr[mid] < num) {
|
||||
lo = mid;
|
||||
} else {
|
||||
hi = mid;
|
||||
}
|
||||
}
|
||||
if (num - arr[lo] <= arr[hi] - num) {
|
||||
return [arr[lo], lo];
|
||||
}
|
||||
return [arr[hi], hi];
|
||||
}
|
||||
|
||||
/**
|
||||
* function that calls find best match function and saves the indexes from a match into a list.
|
||||
* @param tcpdataList
|
||||
* @param serialdataList
|
||||
*/
|
||||
function findSerialDataIndex(tcpdataList, serialdataList) {
|
||||
let allSerialTimes = []
|
||||
|
||||
serialdataList.forEach(sensordata => {
|
||||
if (sensordata.Speed !== 0 && sensordata.HAcc !== 0) {
|
||||
allSpeedsSerial.push(sensordata.Speed)
|
||||
allAccSerial.push(sensordata.HAcc)
|
||||
if(sensordata.Position[1] !== 0 && sensordata.Position[0] !== 0){
|
||||
allSerialCoords.push([sensordata.Position[1], sensordata.Position[0]])
|
||||
}
|
||||
let serialTimestamp = composeTimestamp(sensordata.Timestamp)
|
||||
allSerialTimes.push(serialTimestamp)
|
||||
}
|
||||
})
|
||||
|
||||
tcpdataList.forEach(sensordata => {
|
||||
if (sensordata.Speed !== 0 && sensordata.HAcc !== 0) {
|
||||
let tcpTimestamp = composeTimestamp(sensordata.Timestamp)
|
||||
let index = findBestTimeMatch(tcpTimestamp, allSerialTimes)[1]
|
||||
|
||||
indexes.push(index)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
window.addEventListener("load", function(evt) {
|
||||
|
||||
//------------------------Buttons------------------------------
|
||||
|
||||
let trackings = null;
|
||||
document.getElementById("messungladen").onclick = function(evt) {
|
||||
fetch('http://localhost:3011/trackings/', { method: 'GET'}).then(results => {
|
||||
return results.json()
|
||||
}).then(r => {
|
||||
console.log(r)
|
||||
if (!'data' in r) {
|
||||
return
|
||||
}
|
||||
trackings = r.data
|
||||
let sel = document.getElementById("meas")
|
||||
sel.innerHTML = ''
|
||||
r.data.sort((a,b) => new Date(b.TimeCreated).getTime() - new Date(a.TimeCreated).getTime());
|
||||
r.data.forEach(tracking => {
|
||||
console.log(tracking)
|
||||
let option = document.createElement("option");
|
||||
option.text = tracking.TimeCreated + " Size: " + tracking.Size
|
||||
sel.add(option)
|
||||
})
|
||||
sel.disabled = false
|
||||
document.getElementById("replaystarten").disabled = false
|
||||
|
||||
})
|
||||
};
|
||||
|
||||
document.getElementById("replaystarten").onclick = function(evt) {
|
||||
indexes = []
|
||||
allSpeedsSerial = []
|
||||
allAccSerial = []
|
||||
allSerialCoords = []
|
||||
|
||||
let sel = document.getElementById("meas")
|
||||
console.log(trackings[sel.selectedIndex].UUID)
|
||||
fetch(`http://localhost:3011/trackings/${trackings[sel.selectedIndex].UUID}`, { method: 'GET'}).then(results => {
|
||||
return results.json()
|
||||
}).then(r => {
|
||||
// console.log(r.data.Data)
|
||||
// console.log(r.data)
|
||||
if('SOURCE_SERIAL' in r.data.Data && r.data.Data.SOURCE_SERIAL.length > 0 && 'SOURCE_TCP' in r.data.Data && r.data.Data.SOURCE_TCP.length > 0) {
|
||||
findSerialDataIndex(r.data.Data.SOURCE_TCP, r.data.Data.SOURCE_SERIAL)
|
||||
}
|
||||
if ('SOURCE_TCP' in r.data.Data && r.data.Data.SOURCE_TCP.length > 0) {
|
||||
updateMapTCPbulk(r.data.Data.SOURCE_TCP)
|
||||
addTCPSpeedData(r.data.Data.SOURCE_TCP)
|
||||
}
|
||||
if ('SOURCE_SERIAL' in r.data.Data && r.data.Data.SOURCE_SERIAL.length > 0) {
|
||||
updateMapSERIALbulk(r.data.Data.SOURCE_SERIAL)
|
||||
addSerialSpeedData(r.data.Data.SOURCE_SERIAL)
|
||||
}
|
||||
addDistances(prepareForDistanceCalc(r.data.Data))
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
function prepareForDistanceCalc(data) {
|
||||
if('SOURCE_TCP' in data && data.SOURCE_TCP.length > 0 && 'SOURCE_SERIAL' in data && data.SOURCE_SERIAL.length > 0) {
|
||||
let sensorPoints = [];
|
||||
data.SOURCE_TCP.forEach(element => {
|
||||
if (element.Position[0] !== 0 && element.Position[1] !== 0) {
|
||||
sensorPoints.push({
|
||||
differenceMs: Number.MAX_VALUE,
|
||||
tcp: element,
|
||||
ser: null,
|
||||
})
|
||||
}
|
||||
})
|
||||
sensorPoints.forEach((el, index, arr) => {
|
||||
let tcpTS = Date.parse(el.tcp.Timestamp)
|
||||
data.SOURCE_SERIAL.forEach(serElement => {
|
||||
let serTS = Date.parse(serElement.Timestamp)
|
||||
if (Math.abs(tcpTS - serTS) < el.differenceMs && serElement.Position[0] !== 0 && serElement.Position[1] !== 0) {
|
||||
el.differenceMs = tcpTS - serTS
|
||||
arr[index].ser = serElement
|
||||
}
|
||||
})
|
||||
})
|
||||
// filter differences with more than 50 ms
|
||||
let newSensorPoints = sensorPoints.filter(el => {
|
||||
return Math.abs(el.differenceMs) < 50
|
||||
})
|
||||
console.log("SENSORPOINTs", newSensorPoints)
|
||||
return newSensorPoints
|
||||
} else if ('SOURCE_SERIAL' in data && data.SOURCE_SERIAL.length > 0) {
|
||||
let sensorPoints = [];
|
||||
data.SOURCE_SERIAL.forEach(element => {
|
||||
if (element.Position[0] !== 0 && element.Position[1] !== 0) {
|
||||
sensorPoints.push({
|
||||
differenceMs: Number.MAX_VALUE,
|
||||
tcp: null,
|
||||
ser: element,
|
||||
})
|
||||
}
|
||||
})
|
||||
return sensorPoints
|
||||
} else if ('SOURCE_TCP' in data && data.SOURCE_TCP.length > 0) {
|
||||
let sensorPoints = [];
|
||||
data.SOURCE_TCP.forEach(element => {
|
||||
if (element.Position[0] !== 0 && element.Position[1] !== 0) {
|
||||
sensorPoints.push({
|
||||
differenceMs: Number.MAX_VALUE,
|
||||
tcp: element,
|
||||
ser: null,
|
||||
})
|
||||
}
|
||||
})
|
||||
return sensorPoints
|
||||
}
|
||||
return null
|
||||
}
|
||||
115
static/scripts/speedChart.js
Normal file
115
static/scripts/speedChart.js
Normal file
@ -0,0 +1,115 @@
|
||||
/**
|
||||
* This file defines a line chart used in the full replay page, showing Ublox speeds and
|
||||
* smartphone speeds at a same moment in time in km/h, over time.
|
||||
*
|
||||
* @authors Timo Volkmann, Frank Herkommer.
|
||||
*/
|
||||
|
||||
//List of all speeds sent in by the Ublox
|
||||
let allSpeedsSerial = []
|
||||
|
||||
//Define the line chart and its properties
|
||||
let ctx = document.getElementById('speedChart').getContext('2d');
|
||||
let speedChart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: new Array(),
|
||||
datasets: [{
|
||||
label: 'Ublox speed',
|
||||
backgroundColor: 'rgba(214, 69, 65, 1)',
|
||||
borderColor: 'rgba(214, 69, 65, 1)',
|
||||
borderWidth: 1,
|
||||
fill: false,
|
||||
pointRadius: 0.5,
|
||||
lineTension: 0.5,
|
||||
data: []
|
||||
},
|
||||
{
|
||||
label: 'Smartphone speed',
|
||||
backgroundColor: 'rgba(30, 139, 195, 1)',
|
||||
borderColor: 'rgba(30, 139, 195, 1)',
|
||||
borderWidth: 1,
|
||||
fill: false,
|
||||
pointRadius: 0.5,
|
||||
lineTension: 0.5,
|
||||
data: []
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
scales: {
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
min: 0,
|
||||
max: 250,
|
||||
stepSize: 25
|
||||
}
|
||||
}],
|
||||
xAxes: [{
|
||||
type: 'time',
|
||||
time: {
|
||||
unit: 'second'
|
||||
}
|
||||
}]
|
||||
},
|
||||
animation: {
|
||||
duration: 0
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Function filtering out speed data sent in by the Ublox using only the given indexes calculated in the refull.js file,
|
||||
* and adding the data to the chart.
|
||||
* As there is less smartphone data collected, we only want the Ublox speeds that come in at the moment with the
|
||||
* smallest time difference between the TCP message and the Serial message.
|
||||
*/
|
||||
function addSerialSpeedData(sensordataList) {
|
||||
let speedsSerial = []
|
||||
let times = []
|
||||
|
||||
if(indexes.length > 0){
|
||||
indexes.forEach(index => {
|
||||
speedsSerial.push((allSpeedsSerial[index] * 3.6).toFixed(2))
|
||||
})
|
||||
speedChart.data.datasets[0].data = speedsSerial;
|
||||
speedChart.update();
|
||||
} else {
|
||||
sensordataList.forEach(sensordata => {
|
||||
if (sensordata.Speed === 0) {
|
||||
return;
|
||||
}
|
||||
let speed = sensordata.Speed
|
||||
speedsSerial.push((speed * 3.6).toFixed(2));
|
||||
let time = sensordata.Timestamp
|
||||
times.push(time)
|
||||
|
||||
})
|
||||
speedChart.data.labels = times;
|
||||
speedChart.data.datasets[0].data = speedsSerial;
|
||||
speedChart.update();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to extract only the speeds and Timestamps out of the messages received from the smartphone
|
||||
* and add tem to the chart.
|
||||
* @param sensordataList List of all received messages of the tcp source and their sensor data.
|
||||
*/
|
||||
function addTCPSpeedData(sensordataList) {
|
||||
let speedsTCP = []
|
||||
let times = []
|
||||
|
||||
sensordataList.forEach(sensordata => {
|
||||
if (sensordata.Speed === 0) {
|
||||
return;
|
||||
}
|
||||
let speed = sensordata.Speed
|
||||
speedsTCP.push((speed * 3.6).toFixed(2));
|
||||
let time = sensordata.Timestamp
|
||||
times.push(time)
|
||||
|
||||
})
|
||||
speedChart.data.labels = times;
|
||||
speedChart.data.datasets[1].data = speedsTCP;
|
||||
speedChart.update();
|
||||
}
|
||||
183
static/scripts/speedometer.js
Normal file
183
static/scripts/speedometer.js
Normal file
@ -0,0 +1,183 @@
|
||||
/**
|
||||
* This file defines a doughnut chart used in the live tracking page, representing a speedometer showing
|
||||
* Ublox speeds and smartphone speeds in km/h.
|
||||
*
|
||||
* @authors Timo Volkmann, Frank Herkommer.
|
||||
*/
|
||||
|
||||
let options1 = {
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
datasets: [
|
||||
{
|
||||
label: 'speedTCP',
|
||||
data: [0,100],
|
||||
backgroundColor: [
|
||||
'rgba(30, 139, 195, 1)',
|
||||
'rgba(191, 191, 191, 1)'
|
||||
],
|
||||
borderColor: [
|
||||
'rgba(255, 255, 255 ,1)',
|
||||
'rgba(255, 255, 255 ,1)'
|
||||
],
|
||||
borderWidth: 0
|
||||
},
|
||||
{
|
||||
label: 'speedSERIAl',
|
||||
data: [0, 100],
|
||||
backgroundColor: [
|
||||
'rgba(214, 69, 65, 1)',
|
||||
'rgba(191, 191, 191, 1)'
|
||||
],
|
||||
borderColor: [
|
||||
'rgba(255, 255, 255 ,1)',
|
||||
'rgba(255, 255, 255 ,1)'
|
||||
],
|
||||
borderWidth: 0
|
||||
}
|
||||
]
|
||||
},
|
||||
options: {
|
||||
rotation: Math.PI,
|
||||
circumference: Math.PI,
|
||||
legend: {
|
||||
display: false,
|
||||
enabled: false
|
||||
},
|
||||
tooltips: {
|
||||
enabled: false,
|
||||
display: false
|
||||
},
|
||||
cutoutPercentage: 40
|
||||
}
|
||||
}
|
||||
let options2 = {
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
datasets: [
|
||||
{
|
||||
label: 'speedMarks',
|
||||
data: [50,50,50,50],
|
||||
backgroundColor: [
|
||||
'rgba(30, 130, 76, 1)',
|
||||
'rgba(244, 208, 63, 1)',
|
||||
'rgba(235, 151, 78, 1)',
|
||||
'rgba(217, 30, 24, 1)'
|
||||
],
|
||||
borderColor: [
|
||||
'rgba(30, 130, 76, 1)',
|
||||
'rgba(244, 208, 63, 1)',
|
||||
'rgba(235, 151, 78, 1)',
|
||||
'rgba(217, 30, 24, 1)'
|
||||
],
|
||||
borderWidth: 0
|
||||
},
|
||||
{
|
||||
label: 'transparent',
|
||||
data: [100],
|
||||
backgroundColor: [
|
||||
'rgba(0, 0, 0, 0)'
|
||||
],
|
||||
borderColor: [
|
||||
'rgba(0, 0, 0, 0)'
|
||||
],
|
||||
borderWidth: 2
|
||||
},
|
||||
{
|
||||
label: 'transparent1',
|
||||
data: [100],
|
||||
backgroundColor: [
|
||||
'rgba(0, 0, 0, 0)'
|
||||
],
|
||||
borderColor: [
|
||||
'rgba(0, 0, 0, 0)'
|
||||
],
|
||||
borderWidth: 2
|
||||
},
|
||||
{
|
||||
label: 'transparent2',
|
||||
data: [100],
|
||||
backgroundColor: [
|
||||
'rgba(0, 0, 0, 0)'
|
||||
],
|
||||
borderColor: [
|
||||
'rgba(0, 0, 0, 0)'
|
||||
],
|
||||
borderWidth: 2
|
||||
},
|
||||
{
|
||||
label: 'transparent3',
|
||||
data: [100],
|
||||
backgroundColor: [
|
||||
'rgba(0, 0, 0, 0)'
|
||||
],
|
||||
borderColor: [
|
||||
'rgba(0, 0, 0, 0)'
|
||||
],
|
||||
borderWidth: 2
|
||||
},
|
||||
{
|
||||
label: 'speedMarks1',
|
||||
data: [50,50,50,50],
|
||||
backgroundColor: [
|
||||
'rgba(30, 130, 76, 1)',
|
||||
'rgba(244, 208, 63, 1)',
|
||||
'rgba(235, 151, 78, 1)',
|
||||
'rgba(217, 30, 24, 1)'
|
||||
],
|
||||
borderColor: [
|
||||
'rgba(30, 130, 76, 1)',
|
||||
'rgba(244, 208, 63, 1)',
|
||||
'rgba(235, 151, 78, 1)',
|
||||
'rgba(217, 30, 24, 1)'
|
||||
],
|
||||
borderWidth: 0
|
||||
},
|
||||
]
|
||||
},
|
||||
options: {
|
||||
rotation: Math.PI,
|
||||
circumference: Math.PI,
|
||||
legend: {
|
||||
display: false,
|
||||
enabled: false
|
||||
},
|
||||
tooltips: {
|
||||
enabled: false,
|
||||
display: false
|
||||
},
|
||||
cutoutPercentage: 65
|
||||
}
|
||||
}
|
||||
//chart showing the actual speed of the two devices.
|
||||
let ctx1 = document.getElementById('speedometer').getContext('2d');
|
||||
let mySpeedometer = new Chart(ctx1, options1);
|
||||
//chart adding the different speed areas colored from green to red.
|
||||
let ctx2 = document.getElementById('speedometerSpeeds').getContext('2d');
|
||||
let mySpeedometer2 = new Chart(ctx2, options2);
|
||||
|
||||
/**
|
||||
* Function that adds speed data sent by the Ublox, converted to km/h, to the speedometer.
|
||||
* Called every time a message is received over serial connection from the server.
|
||||
* @param speedSERIAL speed of the Ublox in m/s
|
||||
*/
|
||||
function addSpeedSerial(speedSERIAL){
|
||||
let speedSERIALkmh = (speedSERIAL * 3.6)
|
||||
let speedSERIALpercent = (speedSERIALkmh/250)*100
|
||||
mySpeedometer.data.datasets[1].data = [speedSERIALpercent, 100-speedSERIALpercent];
|
||||
document.getElementById("speedSERIAL").innerHTML = `Ublox: ${speedSERIALkmh.toFixed(1)} km/h`
|
||||
mySpeedometer.update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Function that adds speed data sent by the Smartphone, converted to km/h, to the speedometer.
|
||||
* Called every time a message is received over tcp connection from the server.
|
||||
* @param speedTCP speed of the Smartphone in m/s
|
||||
*/
|
||||
function addSpeedTcp(speedTCP){
|
||||
let speedTCPkmh = (speedTCP * 3.6)
|
||||
let speedTCPpercent = (speedTCPkmh/250)*100;
|
||||
mySpeedometer.data.datasets[0].data = [speedTCPpercent, 100-speedTCPpercent];
|
||||
document.getElementById("speedTCP").innerHTML = `Phone: ${speedTCPkmh.toFixed(1)} km/h`
|
||||
mySpeedometer.update();
|
||||
}
|
||||
@ -1,85 +1,175 @@
|
||||
const GRAPH_RES = 100;
|
||||
var dataSmartphone = [];
|
||||
// Temporary TCP and Serial data used to calculate vincenty distance between two coordinates in realtime.
|
||||
let tempTCPCoords = null;
|
||||
let tempSERIALCoords = null;
|
||||
|
||||
window.addEventListener("load", function(evt) {
|
||||
var orientation = [0,0,0];
|
||||
var multiplier = 180/Math.PI/15
|
||||
var output = document.getElementById("output");
|
||||
var input = document.getElementById("input");
|
||||
var ws;
|
||||
var print = function(message) {
|
||||
var d = document.createElement("div");
|
||||
d.textContent = message;
|
||||
output.appendChild(d);
|
||||
};
|
||||
var print2 = function(message) {
|
||||
var d = document.createElement("p");
|
||||
let output = document.getElementById("output");
|
||||
let checkBoxSmartphone = document.getElementById("checkbox1");
|
||||
let checkBoxUblox = document.getElementById("checkbox2");
|
||||
let ws;
|
||||
|
||||
const wsOnCloseF = function (evt) {
|
||||
ws = null;
|
||||
print2("CLOSED");
|
||||
let intervalId;
|
||||
intervalId = setInterval(() => {
|
||||
console.log("reconnect websocket...")
|
||||
if (ws !== null && ws.CONNECTING) {
|
||||
return
|
||||
}
|
||||
if (ws !== null && ws.OPEN) {
|
||||
clearInterval(intervalId)
|
||||
return
|
||||
}
|
||||
ws = new WebSocket("ws://localhost:3011/ws");
|
||||
ws.onopen = wsOnOpenF
|
||||
ws.onclose = wsOnCloseF
|
||||
ws.onmessage = wsOnMessageF
|
||||
ws.onerror = wsOnErrorF
|
||||
}, 1000)
|
||||
}
|
||||
// function called every time a message is received by the server.
|
||||
const wsOnMessageF = function (evt) {
|
||||
let dat = JSON.parse(evt.data)
|
||||
// If message comes from TCP source call functions to add TCP data != 0 to the charts
|
||||
if ('SOURCE_TCP' in dat) {
|
||||
setIndicatorsTcp(dat.SOURCE_TCP)
|
||||
if(dat.SOURCE_TCP.Orientation[0] !== 0 && dat.SOURCE_TCP.Orientation[1] !== 0 && dat.SOURCE_TCP.Orientation[2] !== 0){
|
||||
let heading = (dat.SOURCE_TCP.Orientation[2]+90)%360
|
||||
renderTCP((dat.SOURCE_TCP.Orientation[0]*Math.PI/180),heading*Math.PI/180,-(dat.SOURCE_TCP.Orientation[1]*Math.PI/180))
|
||||
}
|
||||
if(dat.SOURCE_TCP.Position[1] !== 0 && dat.SOURCE_TCP.Position[0] !== 0){
|
||||
document.getElementById("TCPlong").innerHTML = "Smartphone long: " + dat.SOURCE_TCP.Position[1]
|
||||
document.getElementById("TCPlat").innerHTML = "Smartphone lat: " + dat.SOURCE_TCP.Position[0]
|
||||
updateMapTCP(dat.SOURCE_TCP.Position[1], dat.SOURCE_TCP.Position[0])
|
||||
map.panTo([dat.SOURCE_TCP.Position[1], dat.SOURCE_TCP.Position[0]])
|
||||
tempTCPCoords = dat.SOURCE_TCP
|
||||
}
|
||||
if(dat.SOURCE_TCP.Speed !== 0){
|
||||
addSpeedTcp(dat.SOURCE_TCP.Speed);
|
||||
}
|
||||
if(dat.SOURCE_TCP.HeadDevice !== 0){
|
||||
document.getElementById("compassTCP").innerHTML = " Heading Device: " + dat.SOURCE_TCP.HeadDevice.toFixed(2) + "°"
|
||||
}
|
||||
if(dat.SOURCE_TCP.HeadMotion !== 0) {
|
||||
document.getElementById("compassTCPMot").innerHTML = "Heading Motion: " + dat.SOURCE_TCP.HeadMotion.toFixed(2) + "°"
|
||||
}
|
||||
if(dat.SOURCE_TCP.HAcc !== 0 && dat.SOURCE_TCP.VAcc !== 0){
|
||||
addTCPAccuracy(dat.SOURCE_TCP.HAcc, dat.SOURCE_TCP.VAcc)
|
||||
document.getElementById("tcpHAcc").innerHTML = "Phone HAcc: " + dat.SOURCE_TCP.HAcc.toFixed(2) + " m"
|
||||
document.getElementById("tcpVAcc").innerHTML = "Phone VAcc: " + dat.SOURCE_TCP.VAcc.toFixed(2) + " m"
|
||||
}
|
||||
}
|
||||
|
||||
// If message comes from Serial source call functions to add serial data != 0 to the charts
|
||||
if ('SOURCE_SERIAL' in dat) {
|
||||
setIndicatorsSer(dat.SOURCE_SERIAL)
|
||||
if(dat.SOURCE_SERIAL.Orientation[0] !== 0 && dat.SOURCE_SERIAL.Orientation[2] !== 0){
|
||||
renderSerial(dat.SOURCE_SERIAL.Orientation[0]*Math.PI/180,-dat.SOURCE_SERIAL.Orientation[2]*Math.PI/180,dat.SOURCE_SERIAL.Orientation[1]*Math.PI/180)
|
||||
}
|
||||
if(dat.SOURCE_SERIAL.Position[1] !== 0 && dat.SOURCE_SERIAL.Position[0] !== 0){
|
||||
document.getElementById("SERIALlong").innerHTML = "Ublox long: " + dat.SOURCE_SERIAL.Position[1]
|
||||
document.getElementById("SERIALlat").innerHTML = "Ublox lat: " + dat.SOURCE_SERIAL.Position[0]
|
||||
updateMapSERIAL(dat.SOURCE_SERIAL.Position[1], dat.SOURCE_SERIAL.Position[0])
|
||||
map.panTo([dat.SOURCE_SERIAL.Position[1], dat.SOURCE_SERIAL.Position[0]])
|
||||
tempSERIALCoords = dat.SOURCE_SERIAL
|
||||
if (tempTCPCoords !== null) {
|
||||
|
||||
// calculate distance between coordinates from phone and m8u
|
||||
let tempDist = distVincenty(tempTCPCoords.Position, tempSERIALCoords.Position)
|
||||
// calculate time difference between currently cached measurements from phone and m8u
|
||||
let timeDiff = Date.parse(tempTCPCoords.Timestamp) - Date.parse(tempSERIALCoords.Timestamp)
|
||||
// calculate error estimation: traveled distance in time difference
|
||||
let distError = Math.abs(dat.SOURCE_SERIAL.Speed / 1000 * timeDiff)
|
||||
// remove invalid negative values
|
||||
let distClean = Math.max(tempDist - distError, 0) // set to zero if error greater than diff as this is only an estimation
|
||||
|
||||
addDistanceToBarChart(distClean)
|
||||
document.getElementById("distance").innerHTML = "Distance 2D: " + distClean.toFixed(3) + " m"
|
||||
|
||||
if(distClean <= dat.SOURCE_SERIAL.HAcc){
|
||||
document.getElementById("greenlamp").style.backgroundColor = 'rgba(0, 230, 64, 1)'
|
||||
document.getElementById("yellow").style.backgroundColor = 'rgb(157,117,25)'
|
||||
document.getElementById("redlamp").style.backgroundColor = 'rgba(139, 0, 0, 1)'
|
||||
}
|
||||
else if(distClean <= tempTCPCoords.HAcc){
|
||||
document.getElementById("greenlamp").style.backgroundColor = 'rgba(0, 100, 0, 1)'
|
||||
document.getElementById("yellow").style.backgroundColor = 'rgb(255,199,66)'
|
||||
document.getElementById("redlamp").style.backgroundColor = 'rgba(139, 0, 0, 1)'
|
||||
}
|
||||
else{
|
||||
document.getElementById("greenlamp").style.backgroundColor = 'rgba(0, 100, 0, 1)'
|
||||
document.getElementById("yellow").style.backgroundColor = 'rgb(157,117,25)'
|
||||
document.getElementById("redlamp").style.backgroundColor = 'rgb(255,14,14)'
|
||||
}
|
||||
}
|
||||
tempTCPCoords = null
|
||||
}
|
||||
if(dat.SOURCE_SERIAL.Speed !== 0){
|
||||
addSpeedSerial(dat.SOURCE_SERIAL.Speed);
|
||||
}
|
||||
if(dat.SOURCE_SERIAL.HeadDevice !== 0){
|
||||
document.getElementById("compassSERIAL").innerHTML = "Heading Device: " + dat.SOURCE_SERIAL.HeadDevice.toFixed(2) + "°"
|
||||
}
|
||||
if(dat.SOURCE_SERIAL.HeadMotion !== 0) {
|
||||
document.getElementById("compassSERIALMot").innerHTML = "Heading Motion: " + dat.SOURCE_SERIAL.HeadMotion.toFixed(2) + "°"
|
||||
}
|
||||
if(dat.SOURCE_SERIAL.HAcc !== 0 && dat.SOURCE_SERIAL.VAcc !== 0){
|
||||
addSerialAccuracy(dat.SOURCE_SERIAL.HAcc, dat.SOURCE_SERIAL.VAcc)
|
||||
document.getElementById("serialHAcc").innerHTML = "Ublox HAcc: " + dat.SOURCE_SERIAL.HAcc.toFixed(3) + " m"
|
||||
document.getElementById("serialVAcc").innerHTML = "Ublox VAcc: " + dat.SOURCE_SERIAL.VAcc.toFixed(2) + " m"
|
||||
}
|
||||
}
|
||||
}
|
||||
const wsOnOpenF = function (evt) {
|
||||
print2("OPEN");
|
||||
}
|
||||
const wsOnErrorF = function(evt) {
|
||||
console.log(evt)
|
||||
print2("ERROR: " + evt);
|
||||
}
|
||||
|
||||
ws = new WebSocket("ws://localhost:3011/ws");
|
||||
ws.onopen = wsOnOpenF
|
||||
ws.onclose = wsOnCloseF
|
||||
ws.onmessage = wsOnMessageF
|
||||
ws.onerror = wsOnErrorF
|
||||
|
||||
const print2 = function(message) {
|
||||
let d = document.createElement("p");
|
||||
d.innerText = message;
|
||||
oldNode = output.firstChild
|
||||
output.replaceChild(d, oldNode)
|
||||
};
|
||||
|
||||
// On open send HTTP request corresponding to the chosen Source/s
|
||||
document.getElementById("open").onclick = function(evt) {
|
||||
if (ws && ws.OPEN) {
|
||||
print("Websocket already open")
|
||||
return false;
|
||||
if(checkBoxSmartphone.checked && checkBoxUblox.checked){
|
||||
fetch('http://localhost:3011/trackings?serial=true&tcp=true', { method: 'POST', body: 'some test data'})
|
||||
.then(results => results.json())
|
||||
.then(console.log);
|
||||
}
|
||||
ws = new WebSocket("ws://localhost:3011/ws");
|
||||
ws.onopen = function(evt) {
|
||||
print("OPEN");
|
||||
else if(!checkBoxSmartphone.checked && checkBoxUblox.checked){
|
||||
fetch('http://localhost:3011/trackings?serial=true&tcp=false', { method: 'POST', body: 'some test data'})
|
||||
.then(results => results.json())
|
||||
.then(console.log);
|
||||
}
|
||||
ws.onclose = function(evt) {
|
||||
ws = null;
|
||||
print2("CLOSE");
|
||||
else if(checkBoxSmartphone.checked && !checkBoxUblox.checked){
|
||||
fetch('http://localhost:3011/trackings?serial=false&tcp=true', { method: 'POST', body: 'some test data'})
|
||||
.then(results => results.json())
|
||||
.then(console.log);
|
||||
}
|
||||
else if(!checkBoxSmartphone.checked && !checkBoxUblox.checked){
|
||||
fetch('http://localhost:3011/trackings?serial=false&tcp=false', { method: 'POST', body: 'some test data'})
|
||||
.then(results => results.json())
|
||||
.then(console.log);
|
||||
}
|
||||
ws.onmessage = function(evt) {
|
||||
//print2("RESPONSE: " + evt.data);
|
||||
// let dat = JSON.parse(evt.data)["bmi26x gyroscope"]
|
||||
// let dat = JSON.parse(evt.data)["lsm6dsm gyroscope"]
|
||||
//let dat = JSON.parse(evt.data)["lsm6ds3c gyroscope"]
|
||||
let dat = JSON.parse(evt.data)
|
||||
dataSmartphone.push(dat)
|
||||
//console.log(evt.data)
|
||||
console.log("JSON geparsed onmessage", dat)
|
||||
//console.log(dat.SOURCE_TCP.Orientation)
|
||||
document.getElementById("gyroscopeTCP").style.transform = `rotateX(${dat.SOURCE_TCP.Orientation[0]}deg) rotateY(${dat.SOURCE_TCP.Orientation[1]}deg) rotateZ(${dat.SOURCE_TCP.Orientation[2]}deg)`
|
||||
document.getElementById("gyroscopeSERIAL").style.transform = `rotateX(${dat.SOURCE_SERIAL.Orientation[0]}deg) rotateY(${dat.SOURCE_SERIAL.Orientation[1]}deg) rotateZ(${dat.SOURCE_SERIAL.Orientation[2]}deg)`
|
||||
|
||||
document.getElementById("TCPlong").innerHTML = "Smartphone long: " + dat.SOURCE_TCP.Position[1]
|
||||
document.getElementById("TCPlat").innerHTML = "Smartphone lat: " + dat.SOURCE_TCP.Position[0]
|
||||
document.getElementById("SERIALlong").innerHTML = "Ublox long: " + dat.SOURCE_SERIAL.Position[1]
|
||||
document.getElementById("SERIALlat").innerHTML = "Ublox lat: " + dat.SOURCE_SERIAL.Position[0]
|
||||
document.getElementById("tracking state").innerHTML = "Tracking state: LIVE"
|
||||
|
||||
document.getElementById("diffLong").innerHTML = "Differenz long: " + Math.abs(dat.SOURCE_TCP.Position[1] - dat.SOURCE_SERIAL.Position[1])
|
||||
document.getElementById("diffLat").innerHTML = "Differenz lat: " + Math.abs(dat.SOURCE_TCP.Position[0] - dat.SOURCE_SERIAL.Position[0])
|
||||
/*
|
||||
console.log(dat)
|
||||
orientation[0] += dat[0] * multiplier
|
||||
orientation[1] += dat[1] * multiplier
|
||||
orientation[2] += dat[2] * multiplier
|
||||
// dataset.push(orientation[0])
|
||||
// while (dataset.length >= 50) {
|
||||
// dataset.shift();
|
||||
// }
|
||||
// addData(orientation[0] / multiplier)
|
||||
*/
|
||||
addData(dat.SOURCE_TCP.Orientation[0])
|
||||
updateMapTCP(dat.SOURCE_TCP.Position[1], dat.SOURCE_TCP.Position[0])
|
||||
updateMapSERIAL(dat.SOURCE_SERIAL.Position[1], dat.SOURCE_SERIAL.Position[0])
|
||||
//updateMap(dat.SOURCE_SERIAL.Position[1], dat.SOURCE_SERIAL.Position[0])
|
||||
checkBoxSmartphone.disabled = true;
|
||||
checkBoxUblox.disabled = true;
|
||||
|
||||
// addData(dat[0])
|
||||
//document.getElementById("gyroscope").style.transform = `rotateX(${-orientation[0]}deg) rotateY(${orientation[1]}deg) rotateZ(${-orientation[2]}deg) translateZ(50px)`
|
||||
}
|
||||
ws.onerror = function(evt) {
|
||||
print("ERROR: " + evt.data);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
document.getElementById("send").onclick = function(evt) {
|
||||
if (!ws) {
|
||||
return false;
|
||||
}
|
||||
print("SEND: " + input.value);
|
||||
ws.send(input.value);
|
||||
return false;
|
||||
};
|
||||
document.getElementById("close").onclick = function(evt) {
|
||||
@ -89,4 +179,85 @@ window.addEventListener("load", function(evt) {
|
||||
ws.close();
|
||||
return false;
|
||||
};
|
||||
});
|
||||
|
||||
//------------------------Buttons------------------------------
|
||||
|
||||
/*
|
||||
Provides every Button with the corresponding HTTP request if the websocket is open.
|
||||
*/
|
||||
|
||||
document.getElementById("messungstarten").onclick = function(evt) {
|
||||
if (ws) {
|
||||
fetch('http://localhost:3011/trackings/', { method: 'PATCH', body: 'some data'})
|
||||
.then(results => results.json())
|
||||
.then(console.log);
|
||||
document.getElementById("tracking state").innerHTML = "Tracking state: RECORD"
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
document.getElementById("messungbeenden").onclick = function(evt) {
|
||||
if (ws) {
|
||||
fetch('http://localhost:3011/trackings/', { method: 'PUT', body: 'some data'})
|
||||
.then(results => results.json())
|
||||
.then(console.log);
|
||||
document.getElementById("tracking state").innerHTML = "Tracking state: LIVE"
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
document.getElementById("allesbeenden").onclick = function(evt) {
|
||||
if (ws) {
|
||||
fetch('http://localhost:3011/trackings/', { method: 'DELETE', body: 'some data'})
|
||||
.then(results => results.json())
|
||||
.then(console.log);
|
||||
checkBoxSmartphone.disabled = false;
|
||||
checkBoxUblox.disabled = false;
|
||||
document.getElementById("tracking state").innerHTML = "Tracking state: CLOSED"
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
var trackings = null;
|
||||
document.getElementById("messungladen").onclick = function(evt) {
|
||||
fetch('http://localhost:3011/trackings/', { method: 'GET'}).then(results => {
|
||||
return results.json()
|
||||
}).then(r => {
|
||||
console.log(r)
|
||||
if (!'data' in r) {
|
||||
return
|
||||
}
|
||||
trackings = r.data
|
||||
let sel = document.getElementById("meas")
|
||||
r.data.sort((a,b) => new Date(b.TimeCreated).getTime() - new Date(a.TimeCreated).getTime());
|
||||
r.data.forEach(tracking => {
|
||||
console.log(tracking)
|
||||
let option = document.createElement("option");
|
||||
option.text = tracking.TimeCreated + " Size: " + tracking.Size
|
||||
sel.add(option)
|
||||
})
|
||||
sel.disabled = false
|
||||
document.getElementById("replaystarten").disabled = false
|
||||
|
||||
})
|
||||
};
|
||||
|
||||
document.getElementById("replaystarten").onclick = function(evt) {
|
||||
emptyTCP.features[0].geometry.coordinates = []
|
||||
emptySERIAL.features[0].geometry.coordinates = []
|
||||
|
||||
let sel = document.getElementById("meas")
|
||||
console.log(trackings[sel.selectedIndex].UUID)
|
||||
fetch(`http://localhost:3011/trackings/${trackings[sel.selectedIndex].UUID}?replay=true`, { method: 'GET'}).then(results => {
|
||||
return results.json()
|
||||
}).then(r => {
|
||||
console.log(r.data.Data)
|
||||
})
|
||||
document.getElementById("tracking state").innerHTML = "Tracking state: REPLAY"
|
||||
}
|
||||
|
||||
document.getElementById("fullReplay").onclick = function(evt) {
|
||||
window.open('http://localhost:3011/tracking')
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
476
static/style.css
Normal file
476
static/style.css
Normal file
@ -0,0 +1,476 @@
|
||||
body { margin: 0; padding: 0; }
|
||||
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
|
||||
|
||||
.legend {
|
||||
background-color: #fff;
|
||||
border-radius: 3px;
|
||||
bottom: 30px;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
|
||||
font: 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif;
|
||||
padding: 10px;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.legend h4 {
|
||||
margin: 0 0 10px;
|
||||
}
|
||||
|
||||
.legend div span {
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
height: 10px;
|
||||
margin-right: 5px;
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
body{margin:0; padding:0; font-size:13px; font-family:Georgia, "Times New Roman", Times, serif; color:#919191; background-color:#232323;}
|
||||
|
||||
.float-child {
|
||||
width: 50%;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.sceneMap {
|
||||
width: 200px;
|
||||
height: 50vh;
|
||||
border: 0px solid #CCC;
|
||||
/*margin: 20px;*/
|
||||
perspective: 400px;
|
||||
}
|
||||
|
||||
|
||||
.sceneMap, #map {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.right-col {
|
||||
display: flex;
|
||||
flex-flow: wrap;
|
||||
width: 34%;
|
||||
max-width: 460px;
|
||||
}
|
||||
.left-col {
|
||||
display: flex;
|
||||
flex-flow: wrap;
|
||||
width: calc(66% - 20px);
|
||||
padding-right: 20px;
|
||||
|
||||
}
|
||||
|
||||
.compass-container {
|
||||
display: flex;
|
||||
flex-flow: wrap;
|
||||
}
|
||||
|
||||
.outer {
|
||||
position: relative;
|
||||
width: 300px;
|
||||
height: 200px;
|
||||
margin: 20px;
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
|
||||
canvas {
|
||||
position: absolute;
|
||||
}
|
||||
.speedMin {
|
||||
position: absolute;
|
||||
left: 0%;
|
||||
transform: translate(-50%, 0);
|
||||
font-size: 30px;
|
||||
bottom: 0;
|
||||
margin-bottom: -50px;
|
||||
}
|
||||
.speed14 {
|
||||
position: absolute;
|
||||
left: 8%;
|
||||
transform: translate(-50%, 0);
|
||||
font-size: 20px;
|
||||
bottom: 0;
|
||||
margin-bottom: 90px;
|
||||
}
|
||||
.speedMed {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translate(-50%, 0);
|
||||
font-size: 20px;
|
||||
bottom: 0;
|
||||
margin-bottom: 140px;
|
||||
}
|
||||
.speed34 {
|
||||
position: absolute;
|
||||
left: 92%;
|
||||
transform: translate(-50%, 0);
|
||||
font-size: 20px;
|
||||
bottom: 0;
|
||||
margin-bottom: 90px;
|
||||
}
|
||||
.speedMax {
|
||||
position: absolute;
|
||||
Left: 100%;
|
||||
transform: translate(-50%, 0);
|
||||
font-size: 30px;
|
||||
bottom: 0;
|
||||
margin-bottom: -50px;
|
||||
}
|
||||
|
||||
#compass {
|
||||
position: relative;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
/*margin: 20px;*/
|
||||
}
|
||||
#compass1 {
|
||||
position: relative;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
/*margin: 20px;*/
|
||||
}
|
||||
|
||||
.accuracy-container {
|
||||
display: flex;
|
||||
flex-flow: wrap;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.accuracy-values {
|
||||
margin: 28px 20px 0 20px;
|
||||
}
|
||||
|
||||
.led-container {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
#bezel {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
border-radius: 50%;
|
||||
}
|
||||
#bezelTCP {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
#axis {
|
||||
position: absolute;
|
||||
left: 88px;
|
||||
top: 88px;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background: #ffff;
|
||||
border: 6px solid #666;
|
||||
border-radius: 50%;
|
||||
}
|
||||
#axisTCP {
|
||||
position: absolute;
|
||||
left: 88px;
|
||||
top: 88px;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background: #ffff;
|
||||
border: 6px solid #666;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
#needle {
|
||||
position: absolute;
|
||||
left: 96px;
|
||||
width: 4px;
|
||||
height: 160px;
|
||||
top: 16px;
|
||||
}
|
||||
#needleTCP {
|
||||
position: absolute;
|
||||
left: 96px;
|
||||
width: 4px;
|
||||
height: 160px;
|
||||
top: 16px;
|
||||
}
|
||||
|
||||
#needle:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -1px;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border: 4px solid transparent;
|
||||
border-bottom: 80px solid #FF3600;
|
||||
}
|
||||
|
||||
#needle:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 80px;
|
||||
left: -1px;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border: 4px solid transparent;
|
||||
border-top: 80px solid #666;
|
||||
}
|
||||
#needleTCP:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -1px;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border: 4px solid transparent;
|
||||
border-bottom: 80px solid #FF3600;
|
||||
}
|
||||
|
||||
#needleTCP:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 80px;
|
||||
left: -1px;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border: 4px solid transparent;
|
||||
border-top: 80px solid #666;
|
||||
}
|
||||
|
||||
#N {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 88px;
|
||||
color: #FF3600;
|
||||
}
|
||||
|
||||
#E {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 80px;
|
||||
}
|
||||
|
||||
#S {
|
||||
position: absolute;
|
||||
bottom: 5px;
|
||||
left: 88px;
|
||||
}
|
||||
|
||||
#W {
|
||||
position: absolute;
|
||||
left: 5px;
|
||||
top: 80px;
|
||||
}
|
||||
#NTCP {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 88px;
|
||||
color: #FF3600;
|
||||
}
|
||||
|
||||
#ETCP {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 80px;
|
||||
}
|
||||
|
||||
#STCP {
|
||||
position: absolute;
|
||||
bottom: 5px;
|
||||
left: 88px;
|
||||
}
|
||||
|
||||
#WTCP {
|
||||
position: absolute;
|
||||
left: 5px;
|
||||
top: 80px;
|
||||
}
|
||||
|
||||
.dir {
|
||||
font-family: arial, sans-serif;
|
||||
color: #999;
|
||||
font-size: 20px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.quad {
|
||||
display: block;
|
||||
width: 2px;
|
||||
background: #ddd;
|
||||
height: 130px;
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
left: 98px;
|
||||
}
|
||||
|
||||
#NWSE {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
#NESW {
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
#WE {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
#NWSETCP {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
#NESWTCP {
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
#WETCP {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
|
||||
@-webkit-keyframes spin {
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.scene {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
border: 0px solid #CCC;
|
||||
margin: 70px;
|
||||
perspective: 400px;
|
||||
}
|
||||
|
||||
.lamp {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background-color: gray;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.lamps {
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
}
|
||||
|
||||
.lampinner{
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
position: relative;
|
||||
top: 5px;
|
||||
left: 5px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.cube {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
position: relative;
|
||||
transform-style: preserve-3d;
|
||||
/*transform: translateZ(-100px);*/
|
||||
transition: transform 25ms;
|
||||
}
|
||||
|
||||
.cube.show-front { transform:translateZ(-100px) rotateY( 0deg); }
|
||||
.cube.show-right { transform:translateZ(-100px) rotateY( -90deg); }
|
||||
.cube.show-back { transform:translateZ(-100px) rotateY(-180deg); }
|
||||
.cube.show-left { transform:translateZ(-100px) rotateY( 90deg); }
|
||||
.cube.show-top { transform:translateZ(-100px) rotateX( -90deg); }
|
||||
.cube.show-bottom { transform:translateZ(-100px) rotateX( 90deg); }
|
||||
|
||||
.cube__face {
|
||||
position: absolute;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
border: 1px solid white;
|
||||
line-height: 200px;
|
||||
font-size: 40px;
|
||||
/*font-weight: bold;*/
|
||||
color: white;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.cube__face--front { background: hsla( 0, 100%, 50%, 0.7); }
|
||||
.cube__face--right { background: hsla( 60, 100%, 50%, 0.7); }
|
||||
.cube__face--back { background: hsla(120, 100%, 50%, 0.7); }
|
||||
.cube__face--left { background: hsla(180, 100%, 50%, 0.7); }
|
||||
.cube__face--top { background: hsla(240, 100%, 50%, 0.7); }
|
||||
.cube__face--bottom { background: hsla(300, 100%, 50%, 0.7); }
|
||||
|
||||
.cube__face--front { transform: rotateY( 0deg) translateZ(100px) translateY(50px); height: 100px; line-height: 100px; }
|
||||
.cube__face--right { transform: rotateY( 90deg) translateZ(100px) translateY(50px); height: 100px; line-height: 100px; }
|
||||
.cube__face--back { transform: rotateY(180deg) translateZ(100px) translateY(50px); height: 100px; line-height: 100px; }
|
||||
.cube__face--left { transform: rotateY(-90deg) translateZ(100px) translateY(50px); height: 100px; line-height: 100px; }
|
||||
.cube__face--top { transform: rotateX( 90deg) translateZ(50px); }
|
||||
.cube__face--bottom { transform: rotateX(-90deg) translateZ(50px); }
|
||||
|
||||
label { margin-right: 10px; }
|
||||
|
||||
.slidecontainer {
|
||||
width: 100%;
|
||||
overflow: visible;
|
||||
padding: 10px 0px;
|
||||
}
|
||||
|
||||
#manCalContainer {
|
||||
display: none;
|
||||
}
|
||||
/*.slider {*/
|
||||
/* -webkit-appearance: none;*/
|
||||
/* width: 100%;*/
|
||||
/* height: 25px;*/
|
||||
/* background: #d3d3d3;*/
|
||||
/* outline: none;*/
|
||||
/* opacity: 0.7;*/
|
||||
/* -webkit-transition: .2s;*/
|
||||
/* transition: opacity .2s;*/
|
||||
/*}*/
|
||||
|
||||
.slider:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.slider::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background: #4CAF50;
|
||||
cursor: pointer;
|
||||
border-radius: 50%;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.slider::-moz-range-thumb {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background: #4CAF50;
|
||||
cursor: pointer;
|
||||
border-radius: 50%;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.slider {
|
||||
-webkit-appearance: none;
|
||||
width: 100%;
|
||||
height: 8px;
|
||||
border-radius: 5px;
|
||||
background: #d3d3d3;
|
||||
outline: none;
|
||||
opacity: 0.7;
|
||||
-webkit-transition: opacity .15s ease-in-out;
|
||||
transition: opacity .15s ease-in-out;
|
||||
}
|
||||
|
||||
#viewport {
|
||||
width: 100%;
|
||||
height: 360px;
|
||||
}
|
||||
|
||||
.compass-digital {
|
||||
width: 400px;
|
||||
}
|
||||
@ -7,7 +7,6 @@ import (
|
||||
"github.com/dgraph-io/badger/v2"
|
||||
"github.com/google/uuid"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/tidwall/pretty"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
@ -19,6 +18,7 @@ type badgerStore struct {
|
||||
sensordatDb *badger.DB
|
||||
}
|
||||
|
||||
// Returns a badgerDB K/V Store instance. Opens database if exist or creates a new one in working directory
|
||||
func NewRepository(c *core.Configuration) *badgerStore {
|
||||
dir, _ := os.Getwd()
|
||||
logrus.Debug(dir)
|
||||
@ -69,11 +69,11 @@ func (r *badgerStore) Save(tr core.Tracking) error {
|
||||
}
|
||||
err = r.sensordatDb.Update(func(txn *badger.Txn) error {
|
||||
for _, v := range tr.Data {
|
||||
k := createRecordKey(tr.UUID, v.Source(), v.Servertime)
|
||||
logrus.Trace(v, " len key ->", len(k))
|
||||
k := createRecordKey(tr.UUID, v.Source(), v.Timestamp)
|
||||
//logrus.Trace(v, " len key ->", len(k))
|
||||
j, err2 := json.Marshal(v)
|
||||
logrus.Traceln("save record k/v:\n", tr.UUID.String(), v.Servertime.Format(time.RFC3339Nano))
|
||||
logrus.Traceln(string(pretty.Pretty(j)))
|
||||
logrus.Traceln("save record k/v:\n", tr.UUID.String(), v.Timestamp.Format(time.RFC3339Nano))
|
||||
//logrus.Traceln(string(pretty.Pretty(j)))
|
||||
if err2 != nil {
|
||||
return err2
|
||||
}
|
||||
@ -105,6 +105,7 @@ func (r *badgerStore) Save(tr core.Tracking) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Retrieves all existing Trackings. Only Metadata. If you want actual data of tracking, load a specific one with Load(uuid)
|
||||
func (r *badgerStore) LoadAll() ([]core.TrackingMetadata, error) {
|
||||
var result []core.TrackingMetadata
|
||||
err := r.trackingsDb.View(func(txn *badger.Txn) error {
|
||||
@ -133,6 +134,7 @@ func (r *badgerStore) LoadAll() ([]core.TrackingMetadata, error) {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// Retrieves all data of a tracking from disk
|
||||
func (r *badgerStore) Load(id uuid.UUID) (*core.Tracking, error) {
|
||||
logrus.Debugln("try to load from db...", id)
|
||||
if ok := r.isDbClosed(); ok {
|
||||
@ -171,12 +173,12 @@ func (r *badgerStore) Load(id uuid.UUID) (*core.Tracking, error) {
|
||||
item := it.Item()
|
||||
_, source, recTime := unmarshalDataKey(item.Key())
|
||||
el := core.SensorData{}
|
||||
el.Servertime = recTime
|
||||
el.Timestamp = recTime
|
||||
el.SetSource(source)
|
||||
err2 := item.Value(func(val []byte) error {
|
||||
logrus.Traceln(string(val))
|
||||
//logrus.Traceln(string(val))
|
||||
err3 := json.Unmarshal(val, &el)
|
||||
logrus.Traceln(err3, el)
|
||||
//logrus.Traceln(err3, el)
|
||||
return err3
|
||||
})
|
||||
if err2 != nil {
|
||||
@ -191,11 +193,10 @@ func (r *badgerStore) Load(id uuid.UUID) (*core.Tracking, error) {
|
||||
logrus.Error(err)
|
||||
}
|
||||
|
||||
// implement retrieval of raw data only if needed
|
||||
|
||||
return t, nil
|
||||
}
|
||||
|
||||
// helper function to create []byte key from sensordata element
|
||||
func createRecordKey(uid uuid.UUID, source core.SourceId, timestamp time.Time) []byte {
|
||||
prefix := []byte(uid.String())
|
||||
var i string
|
||||
@ -212,17 +213,17 @@ func createRecordKey(uid uuid.UUID, source core.SourceId, timestamp time.Time) [
|
||||
logrus.Errorln("unable to create key", err)
|
||||
}
|
||||
logrus.Traceln("save as:", string(prefix), string(middle), string(suffix))
|
||||
//binary.BigEndian.PutUint64(suffix, uint64(timestamp.UnixNano()))
|
||||
ret := append(prefix, middle...)
|
||||
return append(ret, suffix...)
|
||||
}
|
||||
|
||||
// helper function to split []byte key back to actual data
|
||||
func unmarshalDataKey(key []byte) (uuid.UUID, core.SourceId, time.Time) {
|
||||
logrus.Trace("key len ->", len(key))
|
||||
|
||||
prefix := string(key[:36])
|
||||
suffix := string(key[37:])
|
||||
middle := string(key[36:37])
|
||||
logrus.Traceln("load as:", prefix, middle, suffix)
|
||||
|
||||
var source core.SourceId
|
||||
switch middle {
|
||||
case "1":
|
||||
@ -238,8 +239,6 @@ func unmarshalDataKey(key []byte) (uuid.UUID, core.SourceId, time.Time) {
|
||||
if err != nil {
|
||||
logrus.Errorln("corrupted key", err)
|
||||
}
|
||||
logrus.Traceln(uid, timestamp)
|
||||
|
||||
//timestamp := time.Unix(0, int64(binary.BigEndian.Uint64(suffix)))
|
||||
return uid, source, timestamp
|
||||
}
|
||||
|
||||
@ -3,178 +3,185 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.bundle.js"></script>
|
||||
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
|
||||
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no"/>
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.js"></script>
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.css" rel="stylesheet" />
|
||||
<style>
|
||||
body { margin: 0; padding: 0; }
|
||||
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
|
||||
</style>
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.css" rel="stylesheet"/>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r124/three.js"></script>
|
||||
<script src="static/scripts/distanceCalc.js"></script>
|
||||
<script src="static/scripts/websocket.js"></script>
|
||||
<style>
|
||||
|
||||
.legend {
|
||||
background-color: #fff;
|
||||
border-radius: 3px;
|
||||
bottom: 30px;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
|
||||
font: 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif;
|
||||
padding: 10px;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.legend h4 {
|
||||
margin: 0 0 10px;
|
||||
}
|
||||
|
||||
.legend div span {
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
height: 10px;
|
||||
margin-right: 5px;
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
body{margin:0; padding:0; font-size:13px; font-family:Georgia, "Times New Roman", Times, serif; color:#919191; background-color:#232323;}
|
||||
|
||||
.float-child {
|
||||
width: 45%;
|
||||
float: left;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.scene {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
border: 0px solid #CCC;
|
||||
margin: 75px;
|
||||
perspective: 400px;
|
||||
}
|
||||
|
||||
.cube {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
position: relative;
|
||||
transform-style: preserve-3d;
|
||||
/*transform: translateZ(-100px);*/
|
||||
/*transition: transform 25ms;*/
|
||||
}
|
||||
|
||||
.cube.show-front { transform:/*translateZ(-100px)*/ rotateY( 0deg); }
|
||||
.cube.show-right { transform:/*translateZ(-100px)*/ rotateY( -90deg); }
|
||||
.cube.show-back { transform:/*translateZ(-100px)*/ rotateY(-180deg); }
|
||||
.cube.show-left { transform:/*translateZ(-100px)*/ rotateY( 90deg); }
|
||||
.cube.show-top { transform:/*translateZ(-100px)*/ rotateX( -90deg); }
|
||||
.cube.show-bottom { transform:/*translateZ(-100px)*/ rotateX( 90deg); }
|
||||
|
||||
.cube__face {
|
||||
position: absolute;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
border: 1px solid white;
|
||||
line-height: 200px;
|
||||
font-size: 40px;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.cube__face--front { background: hsla( 0, 100%, 50%, 0.7); }
|
||||
.cube__face--right { background: hsla( 60, 100%, 50%, 0.7); }
|
||||
.cube__face--back { background: hsla(120, 100%, 50%, 0.7); }
|
||||
.cube__face--left { background: hsla(180, 100%, 50%, 0.7); }
|
||||
.cube__face--top { background: hsla(240, 100%, 50%, 0.7); }
|
||||
.cube__face--bottom { background: hsla(300, 100%, 50%, 0.7); }
|
||||
|
||||
.cube__face--front { transform: rotateY( 0deg) translateZ(100px); }
|
||||
.cube__face--right { transform: rotateY( 90deg) translateZ(100px); }
|
||||
.cube__face--back { transform: rotateY(180deg) translateZ(100px); }
|
||||
.cube__face--left { transform: rotateY(-90deg) translateZ(100px); }
|
||||
.cube__face--top { transform: rotateX( 90deg) translateZ(100px); }
|
||||
.cube__face--bottom { transform: rotateX(-90deg) translateZ(100px); }
|
||||
|
||||
label { margin-right: 10px; }
|
||||
</style>
|
||||
<link rel="stylesheet" type="text/css" href="static/indicators/css/flightindicators.css" />
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
|
||||
<script src="static/indicators/js/jquery.flightindicators.js"></script>
|
||||
<link rel="stylesheet" href="static/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<table style="font-size: small">
|
||||
<tr>
|
||||
<td valign="top" width="50%">
|
||||
<p>Click "Open" to create a connection to the server.
|
||||
</p>
|
||||
<form>
|
||||
<button id="open">Verbinden</button>
|
||||
<button id="close">Trennen</button>
|
||||
<p style="display: none" >
|
||||
<input id="input" type="text" value="Hello world!">
|
||||
<button id="send">Send</button>
|
||||
</p>
|
||||
</form>
|
||||
|
||||
<button id="messung starten">Messung starten</button>
|
||||
<button id="messung beenden">Messung beenden</button>
|
||||
<button id="messung speichern">Messung speichern</button>
|
||||
<button id="messung verwerfen">Messung verwerfen</button>
|
||||
<button id="messung laden">Messung laden</button></li>
|
||||
</td>
|
||||
<td valign="top" width="100%">
|
||||
<div id="output"></div>
|
||||
<div class="controls">
|
||||
<label><input type="checkbox" id="checkbox1" value="smartphone"> TCP</label><br>
|
||||
<label><input type="checkbox" id="checkbox2" value="ublox"> SERIAL</label><br>
|
||||
<button id="open">Livetracking starten</button>
|
||||
<button id="close" style="display: none">Trennen</button>
|
||||
|
||||
<button id="allesbeenden" style="margin-right: 16px;">Pipeline stoppen</button>
|
||||
<button id="messungstarten">Aufnahme starten</button>
|
||||
<button id="messungbeenden" style="margin-right: 16px;">Aufnahme beenden</button>
|
||||
<button id="messungladen" style="margin-right: 16px;">Aufnahmen laden</button>
|
||||
|
||||
<label>Aufnahmen:
|
||||
<select name="meas" id="meas" disabled>
|
||||
</select>
|
||||
</label>
|
||||
<button id="replaystarten" style="margin-right: 16px;" disabled>Wiedergabe starten</button>
|
||||
<button id="fullReplay">TRACKINGANALYSE</button>
|
||||
</div>
|
||||
<br>
|
||||
<label id="tracking state" style="font: 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif">Tracking
|
||||
state: </label><br>
|
||||
<label id="TCPlong" style="font: 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif">Smartphone
|
||||
long: </label>
|
||||
<label id="TCPlat" style="font: 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif">Smartphone lat: </label>
|
||||
<label id="SERIALlong" style="font: 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif">Ublox long: </label>
|
||||
<label id="SERIALlat" style="font: 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif">Ublox lat: </label>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<div id="output"><p>CLOSED</p></div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="float-container">
|
||||
<div class="float-child">
|
||||
<label id="TCPlong" style= "font: 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif">Smartphone long: </label>
|
||||
<label id="TCPlat" style= "font: 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif">Smartphone lat: </label>
|
||||
<label id="SERIALlong" style= "font: 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif">Ublox long: </label>
|
||||
<label id="SERIALlat" style= "font: 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif">Ublox lat: </label>
|
||||
<label id="diffLong" style= "font: 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif">Differenz long: </label>
|
||||
<label id="diffLat" style= "font: 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif">Differenz lat: </label>
|
||||
<div class="scene" style='width: 500px; height: 500px;'>
|
||||
<div id="map" style='width: 500px; height: 500px;'></div>
|
||||
<div class="float-child left-col">
|
||||
<div class="sceneMap">
|
||||
<div id="map"></div>
|
||||
<div id="state-legend" class="legend">
|
||||
<h4>Legende</h4>
|
||||
<div><span style="background-color: yellow"></span>Ublox</div>
|
||||
<div><span style="background-color: blue"></span>Smartphone</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="float-child">
|
||||
<div class="scene">
|
||||
<p style="font-size: large">Smartphone</p>
|
||||
<div id="gyroscopeTCP" class="cube">
|
||||
<div class="cube__face cube__face--front">front</div>
|
||||
<div class="cube__face cube__face--back">back</div>
|
||||
<div class="cube__face cube__face--right">right</div>
|
||||
<div class="cube__face cube__face--left">left</div>
|
||||
<div class="cube__face cube__face--top">top</div>
|
||||
<div class="cube__face cube__face--bottom">bottom</div>
|
||||
<div><span style="background-color: rgba(214, 69, 65, 1)"></span>Ublox</div>
|
||||
<div><span style="background-color: rgba(30, 139, 195, 1)"></span>Smartphone</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="scene">
|
||||
<p style="font-size: large">Ublox</p>
|
||||
<div id="gyroscopeSERIAL" class="cube">
|
||||
<div class="cube__face cube__face--front">front</div>
|
||||
<div class="cube__face cube__face--back">back</div>
|
||||
<div class="cube__face cube__face--right">right</div>
|
||||
<div class="cube__face cube__face--left">left</div>
|
||||
<div class="cube__face cube__face--top">top</div>
|
||||
<div class="cube__face cube__face--bottom">bottom</div>
|
||||
<div class="outer">
|
||||
<div>
|
||||
<label id="speedTCP"
|
||||
style="color: rgba(30, 139, 195, 1); font: 15px 'Helvetica Neue', Arial, Helvetica, sans-serif">Speed
|
||||
Smartphone (km/h): </label><br>
|
||||
<label id="speedSERIAL"
|
||||
style="color: rgba(214, 69, 65, 1); font: 15px 'Helvetica Neue', Arial, Helvetica, sans-serif">Speed
|
||||
Ublox
|
||||
(km/h): </label><br>
|
||||
</div>
|
||||
<div>
|
||||
<canvas id="speedometer" width="320" height="230"></canvas>
|
||||
<canvas id="speedometerSpeeds" width="320" height="230"></canvas>
|
||||
<p class="speedMin">0</p>
|
||||
<p class="speed14">62</p>
|
||||
<p class="speedMed">125</p>
|
||||
<p class="speed34">188</p>
|
||||
<p class="speedMax">250</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="led-container">
|
||||
<div class="lamps">
|
||||
<div class="lamp">
|
||||
<div class="lampinner" id="greenlamp" style="background-color: darkgreen"></div>
|
||||
</div>
|
||||
<div class="lamp">
|
||||
<div class="lampinner" id="yellow" style="background-color: #9D7519"></div>
|
||||
</div>
|
||||
<div class="lamp">
|
||||
<div class="lampinner" id="redlamp" style="background-color: #8b0000"></div>
|
||||
</div>
|
||||
<label style="margin:auto; margin-left: 10px">Smartphone Genauigkeit</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="accuracy-container">
|
||||
<div style="width: 500px; height: 150px;">
|
||||
<canvas id="accuracy" width="500" height="150"></canvas>
|
||||
</div>
|
||||
<div class="accuracy-values">
|
||||
<div class="container" style="width: 150px; height: 70px">
|
||||
<label id="serialHAcc"
|
||||
style="color: rgba(214, 69, 65, 1); font: 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif">Ublox
|
||||
HAcc: </label><br>
|
||||
<label id="tcpHAcc"
|
||||
style="color: rgba(30, 139, 195, 1); font: 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif">Phone
|
||||
HAcc: </label><br>
|
||||
<label id="distance"
|
||||
style="color: rgba(30, 139, 0, 1); font: 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif">
|
||||
Distance: </label>
|
||||
|
||||
</div>
|
||||
<div class="container" style="width: 150px; height: 50px">
|
||||
<label id="serialVAcc"
|
||||
style="color: rgba(214, 69, 65, 1); font: 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif">Ublox
|
||||
VAcc: </label><br>
|
||||
<label id="tcpVAcc"
|
||||
style="color: rgba(30, 139, 195, 1); font: 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif">Phone
|
||||
VAcc: </label><br>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="float-child right-col">
|
||||
<div class="compass-container">
|
||||
<label id="airspeedLabel"
|
||||
style="display:inline-block; width: 200px; margin-right: 0; color: rgba(214, 69, 65, 1); font: 15px 'Helvetica Neue', Arial, Helvetica, sans-serif">Ref. Speed:</label>
|
||||
<label id="altitudeLabel"
|
||||
style="color: rgba(214, 69, 65, 1); font: 15px 'Helvetica Neue', Arial, Helvetica, sans-serif">Altitude: </label><br>
|
||||
<span id="airspeed"></span>
|
||||
<span id="altimeter"></span>
|
||||
<div class="compass-digital">
|
||||
<label id="compassSERIAL"
|
||||
style="display:inline-block; width: 200px; margin-right: 0; color: rgba(214, 69, 65, 1); font: 15px 'Helvetica Neue', Arial, Helvetica, sans-serif"></label>
|
||||
<label id="compassTCP"
|
||||
style="color: rgba(30, 139, 195, 1); font: 15px 'Helvetica Neue', Arial, Helvetica, sans-serif"></label><br>
|
||||
<label id="compassSERIALMot"
|
||||
style="display:inline-block; width: 200px; margin-right: 0; color: rgba(214, 69, 65, 1); font: 15px 'Helvetica Neue', Arial, Helvetica, sans-serif"></label>
|
||||
<label id="compassTCPMot"
|
||||
style="color: rgba(30, 139, 195, 1); font: 15px 'Helvetica Neue', Arial, Helvetica, sans-serif"></label><br>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<span id="headingSer"></span>
|
||||
<span id="headingTcp"></span>
|
||||
<span id="attitudeSer"></span>
|
||||
<span id="attitudeTcp"></span>
|
||||
|
||||
<div>
|
||||
<div id="viewport">
|
||||
</div>
|
||||
<label id="quaternionOffset"
|
||||
style="color: grey; font: 15px 'Helvetica Neue', Arial, Helvetica, sans-serif">Lage Abweichung: </label><br>
|
||||
<div class="slidecontainer">
|
||||
<button id="calibrate">Smartphone Ausrichtung kalibrieren</button>
|
||||
<button id="deleteCalibration">Kalibrierung zurücksetzen</button>
|
||||
<button id="manualCalibration">Manuelle Kalibrierung</button>
|
||||
<div id="manCalContainer">
|
||||
<p><br>Manuelle Kalibrierung</p>
|
||||
<label>Pitch<input type="range" min="-180" max="180" value="0" class="slider" id="pitchRange"
|
||||
style="margin: 10px 0px"></label>
|
||||
<label>Yaw<input type="range" min="-180" max="180" value="0" class="slider" id="yawRange"
|
||||
style="margin: 10px 0px"></label>
|
||||
<label>Roll<input type="range" min="-180" max="180" value="0" class="slider" id="rollRange"
|
||||
style="margin: 10px 0px"></label>
|
||||
</div>
|
||||
</div>
|
||||
<script src="static/scripts/indicators.js"></script>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="static/scripts/map.js"></script>
|
||||
<script src="static/scripts/speedometer.js"></script>
|
||||
|
||||
<script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>
|
||||
<script src="static/scripts/map.js"></script>
|
||||
|
||||
<div style="width: 600px; height: 400px;">
|
||||
<canvas id="myChart" width="400" height="200"></canvas>
|
||||
</div>
|
||||
<script src="static/scripts/chart.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.4/Chart.min.js"></script>
|
||||
<script src="static/scripts/accuracy.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
47
templates/replayFull.html
Normal file
47
templates/replayFull.html
Normal file
@ -0,0 +1,47 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.bundle.js"></script>
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.js"></script>
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.css" rel="stylesheet" />
|
||||
<script src="static/scripts/distanceCalc.js"></script>
|
||||
<script src="static/scripts/refull.js"></script>
|
||||
<link rel="stylesheet" href="static/replayStyle.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="controls">
|
||||
<br>
|
||||
<button id="messungladen" style="margin-right: 16px;">Aufnahmen laden</button>
|
||||
|
||||
<label>Aufnahmen:
|
||||
<select name="meas" id="meas" disabled>
|
||||
</select>
|
||||
</label>
|
||||
<button id="replaystarten" style="margin-right: 16px;" disabled>Öffnen</button>
|
||||
</div>
|
||||
|
||||
<div class="sceneMap">
|
||||
<div id="map" style='width: 1000px; height: 500px;'></div>
|
||||
<div id="state-legend" class="legend">
|
||||
<h4>Legende</h4>
|
||||
<div><span style="background-color: rgba(214, 69, 65, 1)"></span>Ublox</div>
|
||||
<div><span style="background-color: rgba(30, 139, 195, 1)"></span>Smartphone</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="width: 1000px; height: 300px;">
|
||||
<canvas id="speedChart" width="1000" height="300"></canvas>
|
||||
</div>
|
||||
<div style="width: 1000px; height: 300px;">
|
||||
<canvas id="accChart" width="1000" height="300"></canvas>
|
||||
</div>
|
||||
|
||||
|
||||
<script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>
|
||||
<script src="static/scripts/mapFull.js"></script>
|
||||
<script src="static/scripts/speedChart.js"></script>
|
||||
<script src="static/scripts/accChart.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@ -1,3 +1,6 @@
|
||||
// credits to https://github.com/daedaleanai/ublox for basic ubx parsing idea & code
|
||||
// missing ubx messages added and code modified by Timo Volkmann
|
||||
|
||||
// Package ublox provides methods to encode and decode u-Blox 8 / M8 NMEA and UBX messages
|
||||
// as documented in
|
||||
// UBX-13003221 - R20 u-blox 8 / u-blox M8 Receiver description Including protocol specification
|
||||
|
||||
@ -4,12 +4,6 @@ type Message interface {
|
||||
ClassID() uint16
|
||||
}
|
||||
|
||||
//type UbxMessage interface {
|
||||
// Timestamp() (time.Time, error)
|
||||
// Position() ([3]float64, error)
|
||||
// Orientation() ([3]float64, error)
|
||||
//}
|
||||
|
||||
type RawMessage struct {
|
||||
classID uint16
|
||||
Data []byte
|
||||
|
||||
114
web/http.go
114
web/http.go
@ -4,52 +4,40 @@ import (
|
||||
"errors"
|
||||
"git.timovolkmann.de/gyrogpsc/core"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v2/middleware/logger"
|
||||
"github.com/gofiber/template/html"
|
||||
"github.com/gofiber/websocket/v2"
|
||||
"github.com/google/uuid"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func CreateServer(s core.Service, sub core.Subscriber, c *core.Configuration) {
|
||||
func CreateServer(s *core.TrackingService, sub core.Subscriber, c *core.Configuration) {
|
||||
app := fiber.New(fiber.Config{
|
||||
Views: fiberTemplateEngine(c),
|
||||
})
|
||||
app.Static("/static", "static")
|
||||
app.Use(logger.New())
|
||||
app.Static("/static", "./static")
|
||||
|
||||
// Application Main Page
|
||||
app.Get("/", fiberHomeHandler)
|
||||
app.Get("/tracking", fiberTrackingHandler)
|
||||
|
||||
// Websocket
|
||||
app.Get("/ws", websocket.New(createFiberWebsocketHandler(sub)))
|
||||
|
||||
// TODO: Get all SerialPorts
|
||||
// app.Get("/serialports")
|
||||
|
||||
// Tracking persistence controls HTTP JSON RPC API
|
||||
trackings := app.Group("/trackings")
|
||||
trackings.Get("/", allTrackingsHandler(s, c)) // Get all trackings Metadata
|
||||
trackings.Post("/", startPipelineHandler(s, c)) // Initialize new tracking, open websocket and prepare for automatic recording. Toggle ?serial=true and ?tcp=true. Returns trackingId
|
||||
trackings.Patch("/", startRecordingHandler(s, c)) // Starts recording
|
||||
trackings.Put("/", stopRecordingHandler(s, c)) // Stops current recording. Returns trackingId if record was successful
|
||||
trackings.Delete("/", stopAllHandler(s, c)) // Stops websocket connection, pipelines and collectors
|
||||
|
||||
trackings.Get("/", allTrackingsHandler(s, c)) // Get all trackings Metadata
|
||||
trackings.Post("/", startPipelineHandler(s, c)) // Initialize new tracking, open websocket and prepare for automatic recording. Toggle ?serial=true and ?tcp=true. Returns trackingId
|
||||
trackings.Patch("/", startRecordingHandler(s, c)) // Starts recording
|
||||
trackings.Put("/", stopRecordingHandler(s, c)) // Stops current recording. Returns trackingId if record was successful
|
||||
trackings.Delete("/", stopAllHandler(s, c)) // Stops websocket connection, pipelines and collectors
|
||||
trackings.Get("/:trackingId", LoadTrackingHandler(s, c)) // Gets Tracking Metadata and loads sensorRecords from storage.
|
||||
trackings.Delete("/:trackingId", stubhander()) // Deletes Tracking from storage
|
||||
|
||||
trackings.Post("/current", stubhander()) // Starts Replay.
|
||||
trackings.Patch("/current", stubhander()) // Pauses Replay.
|
||||
trackings.Put("/current", stubhander()) // Stops Replay.
|
||||
|
||||
logrus.Fatal(app.Listen(c.Webserver.Port))
|
||||
}
|
||||
|
||||
func stubhander() fiber.Handler {
|
||||
return func(ctx *fiber.Ctx) error {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func LoadTrackingHandler(s core.Service, c *core.Configuration) fiber.Handler {
|
||||
func LoadTrackingHandler(s *core.TrackingService, c *core.Configuration) fiber.Handler {
|
||||
return func(ctx *fiber.Ctx) error {
|
||||
trackId := ctx.Params("trackingId")
|
||||
uid, err := uuid.Parse(trackId)
|
||||
@ -58,18 +46,30 @@ func LoadTrackingHandler(s core.Service, c *core.Configuration) fiber.Handler {
|
||||
ctx.Status(404).JSON(err)
|
||||
return err
|
||||
}
|
||||
tracking, err := s.LoadTracking(uid)
|
||||
var replay bool
|
||||
if ctx.Query("replay", "false") == "true" {
|
||||
replay = true
|
||||
} else {
|
||||
replay = false
|
||||
}
|
||||
tracking, err := s.LoadTracking(uid, replay)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
ctx.Status(404).JSON(err)
|
||||
return err
|
||||
}
|
||||
prepres := map[string]interface{}{}
|
||||
prepres["data"] = *tracking
|
||||
if err != nil {
|
||||
prepres["error"] = err.Error()
|
||||
|
||||
st := struct {
|
||||
core.TrackingMetadata
|
||||
Data map[string][]core.SensorData
|
||||
}{}
|
||||
st.TrackingMetadata = tracking.TrackingMetadata
|
||||
st.Data = make(map[string][]core.SensorData)
|
||||
for _, el := range tracking.Data {
|
||||
st.Data[string(el.Source())] = append(st.Data[string(el.Source())], el)
|
||||
}
|
||||
prepres := make(map[string]interface{})
|
||||
prepres["data"] = st
|
||||
|
||||
err2 := ctx.JSON(prepres)
|
||||
if err2 != nil {
|
||||
ctx.Status(500).JSON(err2)
|
||||
@ -78,18 +78,14 @@ func LoadTrackingHandler(s core.Service, c *core.Configuration) fiber.Handler {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
func allTrackingsHandler(s core.Service, c *core.Configuration) fiber.Handler {
|
||||
func allTrackingsHandler(s *core.TrackingService, c *core.Configuration) fiber.Handler {
|
||||
return func(ctx *fiber.Ctx) error {
|
||||
trackings, err := s.AllTrackings()
|
||||
if err != nil {
|
||||
//ctx.Status(500).JSON(err)
|
||||
//return err
|
||||
}
|
||||
prepres := map[string]interface{}{}
|
||||
|
||||
prepres := make(map[string]interface{})
|
||||
prepres["data"] = trackings
|
||||
if err != nil {
|
||||
prepres["error"] = err.Error()
|
||||
|
||||
}
|
||||
err2 := ctx.JSON(prepres)
|
||||
if err2 != nil {
|
||||
@ -100,7 +96,7 @@ func allTrackingsHandler(s core.Service, c *core.Configuration) fiber.Handler {
|
||||
}
|
||||
}
|
||||
|
||||
func startPipelineHandler(s core.Service, c *core.Configuration) fiber.Handler {
|
||||
func startPipelineHandler(s *core.TrackingService, c *core.Configuration) fiber.Handler {
|
||||
return func(ctx *fiber.Ctx) error {
|
||||
var collecs []core.CollectorType
|
||||
ser := ctx.Query("serial", "true")
|
||||
@ -114,12 +110,9 @@ func startPipelineHandler(s core.Service, c *core.Configuration) fiber.Handler {
|
||||
if tcp == "true" {
|
||||
collecs = append(collecs, core.TCP)
|
||||
}
|
||||
res, err := s.StartPipeline(collecs...)
|
||||
if err != nil {
|
||||
//ctx.Status(500).JSON(err)
|
||||
//return err
|
||||
}
|
||||
prepres := map[string]interface{}{}
|
||||
res, err := s.StartLivetracking(collecs...)
|
||||
|
||||
prepres := make(map[string]interface{})
|
||||
prepres["tracking_state"] = res
|
||||
prepres["data"] = collecs
|
||||
if err != nil {
|
||||
@ -138,14 +131,11 @@ func startPipelineHandler(s core.Service, c *core.Configuration) fiber.Handler {
|
||||
}
|
||||
}
|
||||
|
||||
func startRecordingHandler(s core.Service, c *core.Configuration) fiber.Handler {
|
||||
func startRecordingHandler(s *core.TrackingService, c *core.Configuration) fiber.Handler {
|
||||
return func(ctx *fiber.Ctx) error {
|
||||
rec, err := s.StartRecord()
|
||||
if err != nil {
|
||||
//ctx.Status(500).JSON(err)
|
||||
//return err
|
||||
}
|
||||
prepres := map[string]interface{}{}
|
||||
|
||||
prepres := make(map[string]interface{})
|
||||
prepres["tracking_state"] = "RECORD"
|
||||
prepres["data"] = rec
|
||||
if err != nil {
|
||||
@ -161,14 +151,11 @@ func startRecordingHandler(s core.Service, c *core.Configuration) fiber.Handler
|
||||
}
|
||||
}
|
||||
|
||||
func stopRecordingHandler(s core.Service, c *core.Configuration) fiber.Handler {
|
||||
func stopRecordingHandler(s *core.TrackingService, c *core.Configuration) fiber.Handler {
|
||||
return func(ctx *fiber.Ctx) error {
|
||||
rec, err := s.StopRecord()
|
||||
if err != nil {
|
||||
//ctx.Status(500).JSON(err)
|
||||
//return err
|
||||
}
|
||||
prepres := map[string]interface{}{}
|
||||
|
||||
prepres := make(map[string]interface{})
|
||||
prepres["tracking_state"] = "LIVE"
|
||||
prepres["data"] = rec
|
||||
if err != nil {
|
||||
@ -184,14 +171,11 @@ func stopRecordingHandler(s core.Service, c *core.Configuration) fiber.Handler {
|
||||
}
|
||||
}
|
||||
|
||||
func stopAllHandler(s core.Service, c *core.Configuration) fiber.Handler {
|
||||
func stopAllHandler(s *core.TrackingService, c *core.Configuration) fiber.Handler {
|
||||
return func(ctx *fiber.Ctx) error {
|
||||
rec, err := s.StopAll()
|
||||
if err != nil {
|
||||
//ctx.Status(500).JSON(err)
|
||||
//return err
|
||||
}
|
||||
prepres := map[string]interface{}{}
|
||||
|
||||
prepres := make(map[string]interface{})
|
||||
prepres["tracking_state"] = "STOPPED"
|
||||
prepres["data"] = rec
|
||||
if err != nil {
|
||||
@ -224,9 +208,10 @@ func createFiberWebsocketHandler(s core.Subscriber) func(conn *websocket.Conn) {
|
||||
defer s.Unsubscribe(dispatcherId)
|
||||
for {
|
||||
cmsg := <-channel
|
||||
logrus.Traceln("write to ws:", cmsg)
|
||||
err := c.WriteMessage(websocket.TextMessage, []byte(cmsg))
|
||||
if err != nil {
|
||||
logrus.Info("close websocket connection")
|
||||
logrus.Infoln("close websocket connection", err)
|
||||
c.Close()
|
||||
break
|
||||
}
|
||||
@ -268,3 +253,8 @@ func fiberHomeHandler(c *fiber.Ctx) error {
|
||||
// Render index template
|
||||
return c.Render("index", "ws://"+c.Hostname()+"/ws")
|
||||
}
|
||||
|
||||
func fiberTrackingHandler(c *fiber.Ctx) error {
|
||||
// Render index template
|
||||
return c.Render("replayFull", nil)
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user