commit be3f55354ef58a2db5cb6e097dfde12e884cdf9c Author: Eduardo Silva Date: Sat Oct 19 21:37:51 2024 +0100 First commit It works like this diff --git a/README.md b/README.md new file mode 100644 index 0000000..5947fa4 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# BeamNG SDK +Simple SDK to interact with BeamNG.drive OutGauge data. diff --git a/bngsdk.go b/bngsdk.go new file mode 100644 index 0000000..53fc560 --- /dev/null +++ b/bngsdk.go @@ -0,0 +1,89 @@ +package bngsdk + +import ( + "bytes" + "encoding/binary" + "fmt" + "net" +) + +const ( + UDP_IP = "127.0.0.1" + UDP_PORT = 4444 +) + +type BNGSDK struct { + Addr *net.UDPAddr + Conn *net.UDPConn + Buffer []byte + Data *Outgauge + DataDict map[string]interface{} +} + +func createUDPConnection(ip string, port int) (*net.UDPConn, *net.UDPAddr, error) { + // Define the IP address and port to listen on + addr := &net.UDPAddr{ + IP: net.ParseIP(ip), + Port: port, + } + + // Create a UDP socket + conn, err := net.ListenUDP("udp", addr) + if err != nil { + return nil, nil, err + } + + return conn, addr, nil +} + +// ReadData will read new data from the UDP server +func (sdk *BNGSDK) ReadData() error { + // Receive data from the socket + n, _, err := sdk.Conn.ReadFromUDP(sdk.Buffer) + if err != nil { + fmt.Println("Error reading from UDP:", err) + return err + } + + // Check if enough data was received to fill our struct + if n < binary.Size(Outgauge{}) { + fmt.Println("Received packet too small for Outgauge struct") + return err + } + + // Read the binary data into the struct + reader := bytes.NewReader(sdk.Buffer[:n]) + if err := binary.Read(reader, binary.LittleEndian, sdk.Data); err != nil { + fmt.Println("Error decoding UDP packet:", err) + return err + } + + // Update the local map + sdk.DataDict = sdk.Data.ToMap() + + // this means there's new data + return nil +} + +func (sdk *BNGSDK) Close() { + sdk.Conn.Close() +} + +// Init initializes a BeamNG SDK struct +func Init(ip string, port int) (BNGSDK, error) { + var err error + sdk := BNGSDK{} + + // Create the connection to the OutGauge server + sdk.Conn, sdk.Addr, err = createUDPConnection(ip, port) + if err != nil { + return BNGSDK{}, err + } + + // Initiate the data variables + sdk.Buffer = make([]byte, 1024) + sdk.Data = &Outgauge{} + sdk.DataDict = sdk.Data.ToMap() + + return sdk, nil +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..a0b67f7 --- /dev/null +++ b/go.mod @@ -0,0 +1,7 @@ +module bngsdk + +go 1.22.0 + +require github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07 + +require golang.org/x/sys v0.26.0 // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..5f28ef9 --- /dev/null +++ b/go.sum @@ -0,0 +1,4 @@ +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= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/outgauge.go b/outgauge.go new file mode 100644 index 0000000..5d2c00f --- /dev/null +++ b/outgauge.go @@ -0,0 +1,55 @@ +package bngsdk + +/* TODO + - OG_x Flags + - DL_x Flags +*/ + +// More documentation at https://go.beamng.com/protocols +type Outgauge struct { + Time uint32 // time in milliseconds (to check order) + Car [4]byte // Car name + Flags uint16 // Info (see OG_x below) + Gear int8 // Reverse:0, Neutral:1, First:2... + Plid int8 // Unique ID of viewed player (0 = none) + Speed float32 // M/S + RPM float32 // RPM + Turbo float32 // BAR + EngTemp float32 // C + Fuel float32 // 0 to 1 + OilPressure float32 // BAR + OilTemp float32 // C + DashLights uint32 // Dash lights available (see DL_x below) + ShowLights uint32 // Dash lights currently switched on + Throttle float32 // 0 to 1 + Brake float32 // 0 to 1 + Clutch float32 // 0 to 1 + Display1 [16]byte // Usually Fuel + Display2 [16]byte // Usually Settings + ID int32 // optional - only if OutGauge ID is specified +} + +func (o *Outgauge) ToMap() map[string]interface{} { + return map[string]interface{}{ + "Time": o.Time, // time in milliseconds (to check order) + "Car": o.Car, // Car name + "Flags": o.Flags, // Info (see OG_x below) + "Gear": o.Gear, // Reverse:0, Neutral:1, First:2... + "Plid": o.Plid, // Unique ID of viewed player (0 = none) + "Speed": o.Speed, // M/S + "RPM": o.RPM, // RPM + "Turbo": o.Turbo, // BAR + "EngTemp": o.EngTemp, // C + "Fuel": o.Fuel, // 0 to 1 + "OilPressure": o.OilPressure, // BAR + "OilTemp": o.OilTemp, // C + "DashLights": o.DashLights, // Dash lights available (see DL_x below) + "ShowLights": o.ShowLights, // Dash lights currently switched on + "Throttle": o.Throttle, // 0 to 1 + "Brake": o.Brake, // 0 to 1 + "Clutch": o.Clutch, // 0 to 1 + "Display1": o.Display1, // Usually Fuel + "Display2": o.Display2, // Usually Settings + "ID": o.ID, // optional - only if OutGauge ID is specified + } +}