first approach to implementing virtual binds

virtual binds will just be some middleware that sits between telemetry
primitives and computed values from it like dash lights and a fuel calc
This commit is contained in:
2026-05-31 07:22:06 +01:00
parent 691a51ae8b
commit 2cb30baf6a
4 changed files with 317 additions and 232 deletions
+249 -225
View File
@@ -1,149 +1,5 @@
Windows:
1:
uiwindow:
Dims:
X0: 207
Y0: 412
Width: 111
Height: 57
Decor:
BGColour: 4161
FGColour: 65535
TitleColour: 65535
BorderColour: 63488
TitleSize: 2
TextSize: 4
HasBorder: 1
Padding: 0
Opts:
ShowID: 0
WinType: 2
PreviewValue: "61.4"
Title: BBias
uidata:
WID: 1
TelemetryField: BrakeBias
2:
uiwindow:
Dims:
X0: 710
Y0: 8
Width: 84
Height: 57
Decor:
BGColour: 4161
FGColour: 65535
TitleColour: 65535
BorderColour: 63488
TitleSize: 2
TextSize: 4
HasBorder: 1
Padding: 0
Opts:
ShowID: 0
WinType: 2
PreviewValue: PIT
Title: Pit Sp
uidata:
WID: 2
TelemetryField: Pit Speed Limiter
3:
uiwindow:
Dims:
X0: 74
Y0: 413
Width: 57
Height: 57
Decor:
BGColour: 4161
FGColour: 65535
TitleColour: 65535
BorderColour: 63488
TitleSize: 2
TextSize: 4
HasBorder: 1
Padding: 0
Opts:
ShowID: 0
WinType: 2
PreviewValue: "12"
Title: TC
uidata:
WID: 3
TelemetryField: TC Control
4:
uiwindow:
Dims:
X0: 60
Y0: 91
Width: 85
Height: 57
Decor:
BGColour: 4161
FGColour: 65535
TitleColour: 65535
BorderColour: 63488
TitleSize: 2
TextSize: 4
HasBorder: 1
Padding: 0
Opts:
ShowID: 0
WinType: 2
PreviewValue: "123"
Title: Lap
uidata:
WID: 4
TelemetryField: Lap Number
5:
uiwindow:
Dims:
X0: 142
Y0: 19
Width: 500
Height: 20
Decor:
BGColour: 4161
FGColour: 65535
TitleColour: 65535
BorderColour: 63488
TitleSize: 1
TextSize: 2
HasBorder: 1
Padding: 0
Opts:
ShowID: 0
WinType: 1
PreviewValue: "5678"
Title: TACHO
uidata:
WID: 5
TelemetryField: RPM
6:
uiwindow:
Dims:
X0: 331
Y0: 190
Width: 116
Height: 70
Decor:
BGColour: 4161
FGColour: 65535
TitleColour: 65535
BorderColour: 63488
TitleSize: 2
TextSize: 6
HasBorder: 1
Padding: 0
Opts:
ShowID: 0
WinType: 2
PreviewValue: "234"
Title: SPEEDO
uidata:
WID: 6
TelemetryField: Speed
7:
uiwindow:
Dims:
X0: 9
@@ -165,57 +21,9 @@ Windows:
PreviewValue: "12"
Title: ABS
uidata:
WID: 7
WID: 1
TelemetryField: ABS Control
8:
uiwindow:
Dims:
X0: 590
Y0: 367
Width: 100
Height: 50
Decor:
BGColour: 4161
FGColour: 65535
TitleColour: 65535
BorderColour: 63488
TitleSize: 2
TextSize: 3
HasBorder: 1
Padding: 0
Opts:
ShowID: 0
WinType: 2
PreviewValue: "101.5"
Title: Water T
uidata:
WID: 8
TelemetryField: Water Temperature
9:
uiwindow:
Dims:
X0: 354
Y0: 71
Width: 74
Height: 111
Decor:
BGColour: 4161
FGColour: 65535
TitleColour: 65535
BorderColour: 63488
TitleSize: 2
TextSize: 12
HasBorder: 1
Padding: 0
Opts:
ShowID: 0
WinType: 2
PreviewValue: R
Title: Box
uidata:
WID: 9
TelemetryField: Gear
10:
2:
uiwindow:
Dims:
X0: 140
@@ -237,33 +45,9 @@ Windows:
PreviewValue: "6"
Title: Thr
uidata:
WID: 10
WID: 2
TelemetryField: Throttle Control
11:
uiwindow:
Dims:
X0: 694
Y0: 423
Width: 100
Height: 50
Decor:
BGColour: 4161
FGColour: 65535
TitleColour: 65535
BorderColour: 63488
TitleSize: 2
TextSize: 3
HasBorder: 1
Padding: 0
Opts:
ShowID: 0
WinType: 2
PreviewValue: "4.56"
Title: Oil P
uidata:
WID: 11
TelemetryField: Oil Pressure
12:
3:
uiwindow:
Dims:
X0: 60
@@ -285,9 +69,105 @@ Windows:
PreviewValue: "06:45.123"
Title: Last Lap
uidata:
WID: 12
WID: 3
TelemetryField: Last Lap Time
13:
4:
uiwindow:
Dims:
X0: 74
Y0: 413
Width: 57
Height: 57
Decor:
BGColour: 4161
FGColour: 65535
TitleColour: 65535
BorderColour: 63488
TitleSize: 2
TextSize: 4
HasBorder: 1
Padding: 0
Opts:
ShowID: 0
WinType: 2
PreviewValue: "12"
Title: TC
uidata:
WID: 4
TelemetryField: TC Control
5:
uiwindow:
Dims:
X0: 590
Y0: 367
Width: 100
Height: 50
Decor:
BGColour: 4161
FGColour: 65535
TitleColour: 65535
BorderColour: 63488
TitleSize: 2
TextSize: 3
HasBorder: 1
Padding: 0
Opts:
ShowID: 0
WinType: 2
PreviewValue: "101.5"
Title: Water T
uidata:
WID: 5
TelemetryField: Water Temperature
6:
uiwindow:
Dims:
X0: 354
Y0: 71
Width: 74
Height: 111
Decor:
BGColour: 4161
FGColour: 65535
TitleColour: 65535
BorderColour: 63488
TitleSize: 2
TextSize: 12
HasBorder: 1
Padding: 0
Opts:
ShowID: 0
WinType: 2
PreviewValue: R
Title: Box
uidata:
WID: 6
TelemetryField: Gear
7:
uiwindow:
Dims:
X0: 694
Y0: 423
Width: 100
Height: 50
Decor:
BGColour: 4161
FGColour: 65535
TitleColour: 65535
BorderColour: 63488
TitleSize: 2
TextSize: 3
HasBorder: 1
Padding: 0
Opts:
ShowID: 0
WinType: 2
PreviewValue: "4.56"
Title: Oil P
uidata:
WID: 7
TelemetryField: Oil Pressure
8:
uiwindow:
Dims:
X0: 694
@@ -309,9 +189,9 @@ Windows:
PreviewValue: "101.4"
Title: Oil T
uidata:
WID: 13
WID: 8
TelemetryField: Oil Temperature
14:
9:
uiwindow:
Dims:
X0: 436
@@ -333,5 +213,149 @@ Windows:
PreviewValue: "9999"
Title: Dig Tacho
uidata:
WID: 14
WID: 9
TelemetryField: RPM
10:
uiwindow:
Dims:
X0: 207
Y0: 412
Width: 111
Height: 57
Decor:
BGColour: 4161
FGColour: 65535
TitleColour: 65535
BorderColour: 63488
TitleSize: 2
TextSize: 4
HasBorder: 1
Padding: 0
Opts:
ShowID: 0
WinType: 2
PreviewValue: "61.4"
Title: BBias
uidata:
WID: 10
TelemetryField: BrakeBias
11:
uiwindow:
Dims:
X0: 710
Y0: 8
Width: 84
Height: 57
Decor:
BGColour: 4161
FGColour: 65535
TitleColour: 65535
BorderColour: 63488
TitleSize: 2
TextSize: 4
HasBorder: 1
Padding: 0
Opts:
ShowID: 0
WinType: 2
PreviewValue: PIT
Title: Pit Sp
uidata:
WID: 11
TelemetryField: Pit Speed Limiter
12:
uiwindow:
Dims:
X0: 60
Y0: 91
Width: 85
Height: 57
Decor:
BGColour: 4161
FGColour: 65535
TitleColour: 65535
BorderColour: 63488
TitleSize: 2
TextSize: 4
HasBorder: 1
Padding: 0
Opts:
ShowID: 0
WinType: 2
PreviewValue: "123"
Title: Lap
uidata:
WID: 12
TelemetryField: Lap Number
13:
uiwindow:
Dims:
X0: 142
Y0: 19
Width: 500
Height: 20
Decor:
BGColour: 4161
FGColour: 65535
TitleColour: 65535
BorderColour: 63488
TitleSize: 1
TextSize: 2
HasBorder: 1
Padding: 0
Opts:
ShowID: 0
WinType: 1
PreviewValue: "5678"
Title: TACHO
uidata:
WID: 13
TelemetryField: RPM
14:
uiwindow:
Dims:
X0: 331
Y0: 190
Width: 116
Height: 70
Decor:
BGColour: 4161
FGColour: 65535
TitleColour: 65535
BorderColour: 63488
TitleSize: 2
TextSize: 6
HasBorder: 1
Padding: 0
Opts:
ShowID: 0
WinType: 2
PreviewValue: "234"
Title: SPEEDO
uidata:
WID: 14
TelemetryField: Speed
15:
uiwindow:
Dims:
X0: 359
Y0: 355
Width: 120
Height: 49
Decor:
BGColour: 4161
FGColour: 65535
TitleColour: 65535
BorderColour: 63488
TitleSize: 2
TextSize: 3
HasBorder: 1
Padding: 0
Opts:
ShowID: 0
WinType: 2
PreviewValue: YELLOW
Title: RPMColour
uidata:
WID: 15
TelemetryField: RPM State Colour
+24 -1
View File
@@ -123,13 +123,21 @@ func (i *IRacing) readData() {
return
}
// Read binded data
// Read 1 to 1 data
for _, b := range i.data.ActiveBinds {
v := i.SDK.Vars.Vars[b.Key].Value
b.Transform(v, &i.data.Values[b.ID])
}
// Set up virtual binds
i.logger.Debug("Entering virtual binds loop")
for _, vBind := range i.data.VirtualBinds {
// NOTE: delete the logs here, they are really bad
i.logger.Debug("Processing virtual binds")
vBind.Process(i.data)
}
i.data.PenultimateDataPoll = i.data.LastDataPoll
i.data.LastDataPoll = time.Now()
}
@@ -258,5 +266,20 @@ func (i *IRacing) Subscribe(requestFields map[int16]telem.FieldID) {
boundCheck[id] = true
}
// Subscribe to whatever we need of virtual binds I guess - we need to ensure
// the virtual binds fields are being read
needsRPMColour := false
for _, id := range requestFields {
if id == telem.RPMStateColour {
needsRPMColour = true
}
}
i.logger.Debug(fmt.Sprintf("Subscribing to virtual bind? %+v", needsRPMColour))
if needsRPMColour {
i.logger.Debug("Subscribing to virtual bind")
i.data.VirtualBinds = append(i.data.VirtualBinds, telem.NewRPMLights())
}
i.logger.Debug(fmt.Sprintf("Subscribed: %+v\n", i.data.ActiveBinds))
}
+18 -6
View File
@@ -17,9 +17,11 @@ type FieldMapper struct {
Transform func(any) uint64
}
// VirtualField will define data that is acquired through middleware
// So fuel per lap predictions and so on
type VirtualField struct{}
// VirtualField will derive data from telemetry primitives
// So fuel per lap predictions, compound gauge lights and so on
type VirtualField interface {
Process(td *TelemetryData)
}
// NOTE: Update the iracing SDK to write data to the same map ALWAYS, then
// I can bind that address and read directly from there on the transform
@@ -164,6 +166,8 @@ const (
SessionTime
ReplaySessionTime
Empty
// Virtual Fields -- fields derived from primitive fields
RPMStateColour
MaxFields
)
const FirstField = Speed
@@ -202,7 +206,9 @@ var FieldNames = [MaxFields]string{
// Session Data
SessionTime: "SessionTime",
ReplaySessionTime: "ReplaySessionTime",
Empty: "Emtpy",
// Virtual Fields
RPMStateColour: "RPM State Colour",
Empty: "Emtpy",
}
func GetFieldName(id FieldID) string {
@@ -246,8 +252,14 @@ func (td *TelemetryData) Pack() []byte {
bufPtr := bufferPool.Get().(*[]byte)
buf := (*bufPtr)[:0]
for _, bind := range td.ActiveBinds {
buf = td.Values[bind.ID].Pack(buf)
// for _, bind := range td.ActiveBinds {
// buf = td.Values[bind.ID].Pack(buf)
// }
for k := range td.Values {
if len(td.Values[k].IDs) > 0 {
buf = td.Values[k].Pack(buf)
}
}
// We have to copy here because we have to return the buffer
+26
View File
@@ -0,0 +1,26 @@
package telemetry
type RPMLights struct {
State string
}
func NewRPMLights() *RPMLights {
return &RPMLights{
State: "WHITE",
}
}
func (rl *RPMLights) Process(td *TelemetryData) {
curRPM := td.Values[RPM].Raw
td.Values[RPMStateColour].Type = DataTypeSTRING
if curRPM >= 2000 && curRPM < 4000 {
td.Values[RPMStateColour].Str = "GREEN"
} else if curRPM >= 4000 && curRPM < 6000 {
td.Values[RPMStateColour].Str = "YELLOW"
} else if curRPM >= 6000 {
td.Values[RPMStateColour].Str = "RED"
} else {
td.Values[RPMStateColour].Str = "WHITE"
}
}