Added cobra-cli to stop using the os.Args[] and a logger
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"os"
|
||||
)
|
||||
|
||||
// rootCmd represents the base command when called without any subcommands
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "esdi",
|
||||
Short: "CLI for the dashDisplay project",
|
||||
Long: `Allows the configuration and communication with the dashDisplay`,
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
||||
func Execute() {
|
||||
err := rootCmd.Execute()
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"esdi/logger"
|
||||
"esdi/sources/iracing"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func liveTelemetryCmdAction(cmd *cobra.Command, args []string) {
|
||||
log := logger.GetInstance()
|
||||
|
||||
ddPort, _ := cmd.Flags().GetString("port")
|
||||
outputFile, _ := cmd.Flags().GetString("outputFile")
|
||||
|
||||
log.Printf("Called `live`:\nPort: '%s'\nOutFile: '%s'\n", ddPort, outputFile)
|
||||
|
||||
esdi, err := ESDIInit(ddPort, 115200)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to get Desktop Interface: %v", err)
|
||||
}
|
||||
|
||||
irsdk, err := iracing.Init(nil)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create iRacing interface: %v", err)
|
||||
}
|
||||
|
||||
esdi.Source = &irsdk
|
||||
|
||||
esdi.telemetry()
|
||||
}
|
||||
|
||||
// removeLabelCmd represents the removeLabel command
|
||||
var liveTelemetryCmd = &cobra.Command{
|
||||
Use: "live",
|
||||
Short: "stream data directly from the game",
|
||||
Long: ``,
|
||||
Run: liveTelemetryCmdAction,
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(liveTelemetryCmd)
|
||||
|
||||
// Declare the flags for this command
|
||||
liveTelemetryCmd.Flags().StringP("port", "p", "", "dashDisplay Port")
|
||||
|
||||
// Mark the required ones
|
||||
liveTelemetryCmd.MarkFlagRequired("port")
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"esdi/logger"
|
||||
"esdi/sources/iracing"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func offlineTelemetryCmdAction(cmd *cobra.Command, args []string) {
|
||||
log := logger.GetInstance()
|
||||
|
||||
ddPort, _ := cmd.Flags().GetString("port")
|
||||
inFile, _ := cmd.Flags().GetString("in")
|
||||
outFile, _ := cmd.Flags().GetString("out")
|
||||
|
||||
log.Printf("Called `offline`:\nPort: '%s'\nSource: '%s'\nOutFile: '%s'\n", ddPort, inFile, outFile)
|
||||
|
||||
esdi, err := ESDIInit(ddPort, 115200)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to get Desktop Interface: %v", err)
|
||||
}
|
||||
|
||||
file, err := os.Open(inFile)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to open IBT file: %v", err)
|
||||
}
|
||||
|
||||
irsdk, err := iracing.Init(file)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create iRacing interface: %v", err)
|
||||
}
|
||||
|
||||
irsdk.SDK.FileToExport = outFile
|
||||
esdi.Source = &irsdk
|
||||
|
||||
esdi.telemetry()
|
||||
}
|
||||
|
||||
// removeLabelCmd represents the removeLabel command
|
||||
var offlineTelemetryCmd = &cobra.Command{
|
||||
Use: "offline",
|
||||
Short: "stream data from a file",
|
||||
Long: ``,
|
||||
Run: offlineTelemetryCmdAction,
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(offlineTelemetryCmd)
|
||||
|
||||
// Declare the flags for this command
|
||||
offlineTelemetryCmd.Flags().StringP("port", "p", "", "dashDisplay Port")
|
||||
offlineTelemetryCmd.Flags().StringP("in", "i", "", "source file")
|
||||
offlineTelemetryCmd.Flags().StringP("out", "o", "", "output file")
|
||||
|
||||
// Mark the required ones
|
||||
offlineTelemetryCmd.MarkFlagRequired("port")
|
||||
offlineTelemetryCmd.MarkFlagRequired("in")
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
type GameSource interface {
|
||||
GetData(string) (interface{}, error)
|
||||
UpdateData() error
|
||||
}
|
||||
|
||||
type DataPacket struct {
|
||||
Speed int32
|
||||
Gear int32
|
||||
RPM int32
|
||||
}
|
||||
|
||||
func msToKph(v float32) int {
|
||||
return int((3600 * v) / 1000)
|
||||
}
|
||||
|
||||
func (e *ESDI) telemetry() {
|
||||
// Set the handlers
|
||||
sigc := make(chan os.Signal, 1)
|
||||
signal.Notify(sigc,
|
||||
syscall.SIGHUP,
|
||||
syscall.SIGINT,
|
||||
syscall.SIGTERM,
|
||||
syscall.SIGQUIT,
|
||||
)
|
||||
done := make(chan struct{})
|
||||
|
||||
go func() {
|
||||
s := <-sigc
|
||||
switch s {
|
||||
case syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGHUP:
|
||||
fmt.Printf("Received signal: %v\n", s)
|
||||
fmt.Print("\033[?25h\033[2J\033[H")
|
||||
}
|
||||
close(done)
|
||||
e.Close()
|
||||
}()
|
||||
|
||||
lastTime := time.Now().UnixMilli()
|
||||
lastDataSent := time.Now().UnixMilli()
|
||||
for {
|
||||
select {
|
||||
case <-done:
|
||||
return
|
||||
default:
|
||||
time.Sleep(time.Second / 60)
|
||||
|
||||
var err error
|
||||
var buffer strings.Builder
|
||||
buffer.WriteString("\033[?25l\033[2J\033[H")
|
||||
|
||||
err = e.Source.UpdateData()
|
||||
if err != nil {
|
||||
fmt.Printf("could not update data: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
curGear, err := e.Source.GetData("Gear")
|
||||
if err != nil {
|
||||
log.Fatalf("could not get field `Gear`: %v", err)
|
||||
}
|
||||
|
||||
curRPM, err := e.Source.GetData("RPM")
|
||||
if err != nil {
|
||||
log.Fatalf("could not get field `RPM`: %v", err)
|
||||
}
|
||||
|
||||
curSpeed, err := e.Source.GetData("Speed")
|
||||
if err != nil {
|
||||
log.Fatalf("could not get field `Speed`: %v", err)
|
||||
}
|
||||
|
||||
gear := int32(curGear.(int))
|
||||
rpm := int32(curRPM.(float32))
|
||||
speed := int32(msToKph(curSpeed.(float32)))
|
||||
|
||||
buffer.WriteString(fmt.Sprintf("Gear: %d, RPM: %d, Speed: %d", gear, rpm, speed))
|
||||
|
||||
curTime := time.Now().UnixMilli()
|
||||
message := fmt.Sprintf("%d,%d\n", gear-1, rpm)
|
||||
buffer.WriteString("\n" + message)
|
||||
|
||||
messageWasSentMark := "N"
|
||||
if curTime-lastDataSent > 25 {
|
||||
packet := DataPacket{
|
||||
Speed: speed,
|
||||
Gear: gear,
|
||||
RPM: rpm,
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
err = binary.Write(&buf, binary.LittleEndian, packet)
|
||||
|
||||
_, err = e.SerialConn.Write(buf.Bytes())
|
||||
if err != nil {
|
||||
log.Printf("Unable to write data: %v", err)
|
||||
break
|
||||
}
|
||||
|
||||
messageWasSentMark = "Y"
|
||||
lastDataSent = curTime
|
||||
}
|
||||
|
||||
buffer.WriteString(" -> " + messageWasSentMark)
|
||||
if curTime-lastTime > 100 {
|
||||
fmt.Print(buffer.String())
|
||||
lastTime = curTime
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
e.Close()
|
||||
}
|
||||
@@ -3,12 +3,15 @@ module esdi
|
||||
go 1.23.2
|
||||
|
||||
require (
|
||||
github.com/ESilva15/gobngsdk v0.0.1
|
||||
github.com/ESilva15/goirsdk v0.0.0-20241105180527-300c86190b42
|
||||
github.com/ESilva15/gobngsdk v0.0.2
|
||||
github.com/ESilva15/goirsdk v0.0.4
|
||||
github.com/spf13/cobra v1.8.1
|
||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
golang.org/x/sys v0.26.0 // indirect
|
||||
golang.org/x/text v0.19.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
github.com/ESilva15/gobngsdk v0.0.1 h1:EbzIp3pTycqOXbGEX8omhhyaR+N9vixQ8/xSXCbYplQ=
|
||||
github.com/ESilva15/gobngsdk v0.0.1/go.mod h1:3BpgdToILwl+w3IjUJinK9AzYqUefnQBJbfYlR6Ibbk=
|
||||
github.com/ESilva15/goirsdk v0.0.0-20241105180527-300c86190b42 h1:66k8QHzJWrC0Ke2OGQvjFkQUusGfASOsLzfOS0uHoII=
|
||||
github.com/ESilva15/goirsdk v0.0.0-20241105180527-300c86190b42/go.mod h1:Vtqm7KbFJ4pjDSz2pUI4TaMWtnVQXn5m7Ee3vmo9yNc=
|
||||
github.com/ESilva15/gobngsdk v0.0.2 h1:N6stNOE14Wg80BAZMFu/Qd9Qa/J0DmExCfdPoDf7lco=
|
||||
github.com/ESilva15/gobngsdk v0.0.2/go.mod h1:cKLaZRgM0tGGXDvosaSjHnxeyC5Y6rg7zCLqEUJnOzw=
|
||||
github.com/ESilva15/goirsdk v0.0.4 h1:bF4roqOsY4RsKzBjGTsuPuETTtmwccnzYBB2TlQ9mfE=
|
||||
github.com/ESilva15/goirsdk v0.0.4/go.mod h1:Vtqm7KbFJ4pjDSz2pUI4TaMWtnVQXn5m7Ee3vmo9yNc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
|
||||
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07 h1:UyzmZLoiDWMRywV4DUYb9Fbt8uiOSooupjTq10vpvnU=
|
||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
|
||||
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package logger
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var l *log.Logger
|
||||
var once sync.Once
|
||||
|
||||
func createLogger() {
|
||||
l = log.New(os.Stdout, "esdi", log.LstdFlags | log.Lshortfile)
|
||||
}
|
||||
|
||||
func GetInstance() *log.Logger {
|
||||
once.Do(func() {
|
||||
createLogger()
|
||||
})
|
||||
|
||||
return l
|
||||
}
|
||||
@@ -1,152 +1,5 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"esdi/sources/iracing"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
type GameSource interface {
|
||||
GetData(string) (interface{}, error)
|
||||
UpdateData() error
|
||||
}
|
||||
|
||||
type DataPacket struct {
|
||||
Speed int32
|
||||
Gear int32
|
||||
RPM int32
|
||||
}
|
||||
|
||||
func msToKph(v float32) int {
|
||||
return int((3600 * v) / 1000)
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Set the handlers
|
||||
sigc := make(chan os.Signal, 1)
|
||||
signal.Notify(sigc,
|
||||
syscall.SIGHUP,
|
||||
syscall.SIGINT,
|
||||
syscall.SIGTERM,
|
||||
syscall.SIGQUIT,
|
||||
)
|
||||
done := make(chan struct{})
|
||||
|
||||
if len(os.Args) == 3 {
|
||||
fmt.Printf("Port: %s\n", os.Args[1])
|
||||
fmt.Printf("File: %s\n", os.Args[2])
|
||||
} else {
|
||||
log.Fatal("Wrong usage.")
|
||||
}
|
||||
|
||||
esdi, err := ESDIInit(os.Args[1], 115200)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to get Desktop Interface: %v", err)
|
||||
}
|
||||
|
||||
file, err := os.Open(os.Args[2])
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to open IBT file: %v", err)
|
||||
}
|
||||
|
||||
irsdk, err := iracing.Init(file)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create iRacing interface: %v", err)
|
||||
}
|
||||
|
||||
esdi.Source = &irsdk
|
||||
|
||||
go func() {
|
||||
s := <-sigc
|
||||
switch s {
|
||||
case syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGHUP:
|
||||
fmt.Printf("Received signal: %v\n", s)
|
||||
fmt.Print("\033[?25h\033[2J\033[H")
|
||||
}
|
||||
close(done)
|
||||
esdi.Close()
|
||||
}()
|
||||
|
||||
lastTime := time.Now().UnixMilli()
|
||||
lastDataSent := time.Now().UnixMilli()
|
||||
for {
|
||||
select {
|
||||
case <-done:
|
||||
return
|
||||
default:
|
||||
time.Sleep(time.Second / 60)
|
||||
|
||||
var err error
|
||||
var buffer strings.Builder
|
||||
buffer.WriteString("\033[?25l\033[2J\033[H")
|
||||
|
||||
err = esdi.Source.UpdateData()
|
||||
if err != nil {
|
||||
fmt.Printf("could not update data: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
curGear, err := esdi.Source.GetData("Gear")
|
||||
if err != nil {
|
||||
log.Fatalf("could not get field `Gear`: %v", err)
|
||||
}
|
||||
|
||||
curRPM, err := esdi.Source.GetData("RPM")
|
||||
if err != nil {
|
||||
log.Fatalf("could not get field `RPM`: %v", err)
|
||||
}
|
||||
|
||||
curSpeed, err := esdi.Source.GetData("Speed")
|
||||
if err != nil {
|
||||
log.Fatalf("could not get field `Speed`: %v", err)
|
||||
}
|
||||
|
||||
gear := int32(curGear.(int))
|
||||
rpm := int32(curRPM.(float32))
|
||||
speed := int32(msToKph(curSpeed.(float32)))
|
||||
|
||||
buffer.WriteString(fmt.Sprintf("Gear: %d, RPM: %d, Speed: %d", gear, rpm, speed))
|
||||
|
||||
curTime := time.Now().UnixMilli()
|
||||
message := fmt.Sprintf("%d,%d\n", gear-1, rpm)
|
||||
buffer.WriteString("\n" + message)
|
||||
|
||||
messageWasSentMark := "N"
|
||||
if curTime-lastDataSent > 25 {
|
||||
packet := DataPacket{
|
||||
Speed: speed,
|
||||
Gear: gear,
|
||||
RPM: rpm,
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
err = binary.Write(&buf, binary.LittleEndian, packet)
|
||||
|
||||
_, err = esdi.SerialConn.Write(buf.Bytes())
|
||||
if err != nil {
|
||||
log.Printf("Unable to write data: %v", err)
|
||||
break
|
||||
}
|
||||
|
||||
messageWasSentMark = "Y"
|
||||
lastDataSent = curTime
|
||||
}
|
||||
|
||||
buffer.WriteString(" -> " + messageWasSentMark)
|
||||
if curTime-lastTime > 100 {
|
||||
fmt.Print(buffer.String())
|
||||
lastTime = curTime
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
esdi.Close()
|
||||
Execute()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user