Added cobra-cli to stop using the os.Args[] and a logger

This commit is contained in:
2025-01-06 14:42:06 +00:00
parent 519446c20f
commit b8e7725510
8 changed files with 299 additions and 154 deletions
+22
View File
@@ -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)
}
}
+49
View File
@@ -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")
}
+61
View File
@@ -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")
}
+127
View File
@@ -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()
}
+5 -2
View File
@@ -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
+12 -4
View File
@@ -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=
+22
View File
@@ -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 -148
View File
@@ -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()
}