add the identification ID for a telemetry field

we will use this so the serial device knows where to send the data
This commit is contained in:
2026-03-11 21:20:17 +00:00
parent 15ab85dbe1
commit 05af404db1
5 changed files with 33 additions and 17 deletions
+3 -2
View File
@@ -121,12 +121,12 @@ func (i *IRacing) Stream() (<-chan telem.TelemetryData, error) {
return i.streamCh, nil
}
func (i *IRacing) Subscribe(requestFields []telem.FieldID) {
func (i *IRacing) Subscribe(requestFields map[int16]telem.FieldID) {
i.logger.Debug(fmt.Sprintf("Len Req: %d\n", len(requestFields)))
i.data.ActiveBinds = make([]telem.BoundField, 0, len(requestFields))
for _, id := range requestFields {
for winID, id := range requestFields {
// Translate the UI FieldIDs to this provider's field names
sdkKey, ok := internalToSDKFieldNames[id]
if !ok {
@@ -178,6 +178,7 @@ func (i *IRacing) Subscribe(requestFields []telem.FieldID) {
}
}
i.data.Values[id].ID = winID
i.data.ActiveBinds = append(i.data.ActiveBinds, binding)
}
+8 -4
View File
@@ -47,6 +47,7 @@ const (
// application.
// From my testing, using an uint64 bucket is around 50x faster than any
type TelemetryField struct {
ID int16 // Identification: I have to learn how I will use this on other devices
Type DataType
Raw uint64
Str string // Only to be used with DataTypeSTRING
@@ -54,17 +55,20 @@ type TelemetryField struct {
// Pack will pack this current TelemetryField into bytes to send over the wire
// Format:
// 0x00 - DataType
// 0x01 - if its a (u)int8
// 0x00 - Field ID
// 0x00 |
// 0x01 - DataType
// 0x02 - if its a (u)int8
// or
// 0x01 - if its a (u)int16 - first byte
// 0x01 - if its a (u)int16 - second byte
// 0x02 - if its a (u)int16 - first byte
// 0x02 - if its a (u)int16 - second byte
// or
// 0x02 - str len max is 255 chars
// [0x02] - str
func (tf *TelemetryField) Pack(dest []byte) []byte {
// NOTE: maybe we can have a pool of these so we don't have to create them here
// or whatever
dest = append(dest, uint8(tf.ID), uint8(tf.ID>>8))
dest = append(dest, uint8(tf.Type))
switch tf.Type {
+15 -7
View File
@@ -17,51 +17,57 @@ func Test_TelemetryField(t *testing.T) {
{
name: "test_max_uint8",
tf: TelemetryField{
ID: 0x01,
Type: DataTypeUINT8,
Raw: uint64(math.MaxUint8),
},
expect: []byte{0x00, 0xFF},
expect: []byte{0x01, 0x00, 0x00, 0xFF},
},
{
name: "test_max_int8",
tf: TelemetryField{
ID: 0x02,
Type: DataTypeINT8,
Raw: uint64(math.MaxInt8),
},
expect: []byte{0x01, 0x7F},
expect: []byte{0x02, 0x00, 0x01, 0x7F},
},
{
name: "test_max_uint16",
tf: TelemetryField{
ID: 0x03,
Type: DataTypeUINT16,
Raw: uint64(math.MaxUint16),
},
expect: []byte{0x02, 0xFF, 0xFF},
expect: []byte{0x03, 0x00, 0x02, 0xFF, 0xFF},
},
{
name: "test_max_int16",
tf: TelemetryField{
ID: 0x04,
Type: DataTypeINT16,
Raw: uint64(math.MaxInt16),
},
expect: []byte{0x03, 0xFF, 0x7F},
expect: []byte{0x04, 0x00, 0x03, 0xFF, 0x7F},
},
{
name: "test_string",
tf: TelemetryField{
ID: 0x05,
Type: DataTypeSTRING,
Str: "a cool string!",
},
expect: []byte{0x08, 0x0E, 0x61, 0x20, 0x63, 0x6F, 0x6F, 0x6C, 0x20, 0x73,
expect: []byte{0x05, 0x00, 0x08, 0x0E, 0x61, 0x20, 0x63, 0x6F, 0x6F, 0x6C, 0x20, 0x73,
0x74, 0x72, 0x69, 0x6E, 0x67, 0x21},
},
{
name: "test_char",
tf: TelemetryField{
ID: 0x06,
Type: DataTypeCHAR,
Raw: uint64('R'),
},
expect: []byte{0x09, 0x52},
expect: []byte{0x06, 0x00, 0x09, 0x52},
},
}
@@ -92,16 +98,18 @@ func Test_TelemetryData(t *testing.T) {
}
data.Values[Speed] = TelemetryField{
ID: 0x01,
Type: DataTypeUINT16,
Raw: uint64(254),
}
data.Values[Gear] = TelemetryField{
ID: 0x02,
Type: DataTypeCHAR,
Raw: uint64('R'),
}
expect := []byte{0x02, 0xFE, 0x00, 0x09, 0x52}
expect := []byte{0x01, 0x00, 0x02, 0xFE, 0x00, 0x02, 0x00, 0x09, 0x52}
result := data.Pack()
if !bytes.Equal(result, expect) {
+1 -1
View File
@@ -3,5 +3,5 @@ package telemetry
type TelemetryProvider interface {
Stream() (<-chan TelemetryData, error)
Subscribe([]FieldID)
Subscribe(map[int16]FieldID)
}
+6 -3
View File
@@ -89,12 +89,15 @@ func (sc *StreamingCtrl) Start() {
// goes into the layout tool, sets up the data to transmit to his devices and
// then comes here to stream that data. We call this to set the fields the user
// has subscrived to in his tooling
//
// Performance reasoning: this is not used during the high frequency data transmission
// so we can get away with using a map for convenience here
func (sc *StreamingCtrl) SetInternalState() {
// Get the subscribed fields
fields := make([]telemetry.FieldID, 0, len(sc.Service.CDash.State.Layout.Windows))
fields := make(map[int16]telemetry.FieldID, len(sc.Service.CDash.State.Layout.Windows))
for _, w := range sc.Service.CDash.State.Layout.Windows {
fieldID, _ := telemetry.GetFieldID(w.UIData.TelemetryField)
fields = append(fields, fieldID)
fields[w.UIData.IDX] = fieldID
}
sc.TelemServ.ActiveProvider.Subscribe(fields)