From 5192e6d7ce62f3a181056f60d2a610093c7bc6a7 Mon Sep 17 00:00:00 2001 From: Bharat Kathi Date: Thu, 6 Feb 2025 22:29:23 -0800 Subject: [PATCH] finalized message for incoming bytes, added some tests --- message.go | 19 ++++++++--- message_test.go | 91 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+), 4 deletions(-) diff --git a/message.go b/message.go index e7c2100..5586fe4 100644 --- a/message.go +++ b/message.go @@ -20,6 +20,7 @@ func (m Message) Size() int { } // FillFromBytes fills the Fields of a Message with the provided byte array. +// It decodes the bytes into integer values and stores them in the Value of each Field. // It returns an error if the data length does not match the size of the Message. func (m Message) FillFromBytes(data []byte) error { if len(data) != m.Size() { @@ -29,12 +30,13 @@ func (m Message) FillFromBytes(data []byte) error { for i, field := range m { field.Bytes = data[counter : counter+field.Size] counter += field.Size - m[i] = field + m[i] = field.Decode() } return nil } // FillFromInts fills the Fields of a Message with the provided integers. +// It encodes the integers into bytes and stores them in the Bytes of each Field. // It returns an error if the number of integers does not match the number of Fields in the Message. func (m Message) FillFromInts(ints []int) error { if len(ints) != m.Length() { @@ -42,6 +44,10 @@ func (m Message) FillFromInts(ints []int) error { } for i, field := range m { field.Value = ints[i] + field, err := field.Encode() + if err != nil { + return err + } m[i] = field } return nil @@ -122,9 +128,14 @@ func (f Field) Encode() (Field, error) { return f, err } -// CheckBit takes a Field object and a bit position, and returns true if the bit at the given position is set to 1, otherwise false. -func (f Field) CheckBit(bit int) bool { - return (f.Bytes[0] & (1 << bit)) != 0 +// CheckBit takes a Field object and a bit position, and returns the integer value of the bit at the given position (0 or 1). +func (f Field) CheckBit(bit int) int { + byteIndex := bit / 8 + bitPosition := bit % 8 + if byteIndex >= len(f.Bytes) { + return 0 + } + return int(f.Bytes[byteIndex] & (1 << bitPosition)) } // ExportSignals takes a Field object and exports it as an array of signals. diff --git a/message_test.go b/message_test.go index 4def633..73d24fc 100644 --- a/message_test.go +++ b/message_test.go @@ -12,3 +12,94 @@ func TestTimestamp(t *testing.T) { fmt.Println(now) fmt.Printf("Size of timestamp: %d bytes\n", unsafe.Sizeof(now)) } + +func TestMessage(t *testing.T) { + ecuStatusMessage := Message{ + NewField("ecu_state", 1, Unsigned, BigEndian, nil), + NewField("ecu_status_flags", 3, Unsigned, BigEndian, func(f Field) []Signal { + signals := []Signal{} + bitMap := []string{ + "ecu_status_acu", + "ecu_status_inv_one", + "ecu_status_inv_two", + "ecu_status_inv_three", + "ecu_status_inv_four", + "ecu_status_fan_one", + "ecu_status_fan_two", + "ecu_status_fan_three", + "ecu_status_fan_four", + "ecu_status_fan_five", + "ecu_status_fan_six", + "ecu_status_fan_seven", + "ecu_status_fan_eight", + "ecu_status_dash", + "ecu_status_steering", + } + for i := 0; i < len(bitMap); i++ { + signals = append(signals, Signal{ + Name: bitMap[i], + Value: float64(f.CheckBit(i)), + RawValue: f.CheckBit(i), + }) + } + return signals + }), + NewField("ecu_maps", 1, Unsigned, BigEndian, func(f Field) []Signal { + signals := []Signal{} + signals = append(signals, Signal{ + Name: "ecu_power_level", + Value: float64((f.Value >> 4) & 0x0F), + RawValue: (f.Value >> 4) & 0x0F, + }) + signals = append(signals, Signal{ + Name: "ecu_torque_map", + Value: float64(f.Value & 0x0F), + RawValue: f.Value & 0x0F, + }) + return signals + }), + NewField("ecu_max_cell_temp", 1, Unsigned, BigEndian, func(f Field) []Signal { + signals := []Signal{} + signals = append(signals, Signal{ + Name: "ecu_max_cell_temp", + Value: float64(f.Value) * 0.25, + RawValue: f.Value, + }) + return signals + }), + NewField("ecu_acu_state_of_charge", 1, Unsigned, BigEndian, func(f Field) []Signal { + signals := []Signal{} + signals = append(signals, Signal{ + Name: "ecu_acu_state_of_charge", + Value: float64(f.Value) * 20 / 51, + RawValue: f.Value, + }) + return signals + }), + NewField("ecu_glv_state_of_charge", 1, Unsigned, BigEndian, func(f Field) []Signal { + signals := []Signal{} + signals = append(signals, Signal{ + Name: "ecu_glv_state_of_charge", + Value: float64(f.Value) * 20 / 51, + RawValue: f.Value, + }) + return signals + }), + } + t.Run("Invalid byte length", func(t *testing.T) { + err := ecuStatusMessage.FillFromBytes([]byte{0, 0}) + if err == nil { + t.Errorf("Expected error, got nil") + } + }) + t.Run("Valid byte length", func(t *testing.T) { + err := ecuStatusMessage.FillFromBytes([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) + if err != nil { + t.Errorf("Expected nil, got %v", err) + } + signals := ecuStatusMessage.ExportSignals() + for _, signal := range signals { + fmt.Printf("%s: %f\n", signal.Name, signal.Value) + } + }) +}