Files
lingniu-vehicle-ingest/go/vehicle-gateway/internal/feichibridge/encoder_test.go
2026-07-27 16:46:15 +08:00

97 lines
3.0 KiB
Go

package feichibridge
import (
"encoding/binary"
"fmt"
"strings"
"testing"
"time"
"lingniu-vehicle-ingest/go/vehicle-gateway/internal/protocol/gb32960"
)
func TestDataFrameMapsFeichiFields(t *testing.T) {
at := time.Date(2026, 7, 17, 14, 5, 6, 0, shanghai)
record := Record{
"2000": "2026-07-17 14:05:06",
"2201": "42.3", "2202": "12345.6", "2203": "D 0 0",
"2208": "35", "2209": "0", "2213": "纯电",
"2214": "工作", "2301": "未充电状态", "3201": "启动状态",
"2613": "550.2", "2614": "-20.5", "2617": "2200", "7615": "78",
"2501": "有效定位", "2502": "113.2644", "2503": "23.1291",
"2601": "1", "2602": "8", "2603": "3.955",
"2604": "1", "2605": "26", "2606": "3.821",
"2607": "1", "2608": "3", "2609": "48",
"2610": "1", "2611": "9", "2612": "37",
"2003": "1:3.900_3.901_3.902",
"2103": "1:35_36_37", "2115": "44", "2119": "6.0", "100016": "20.8",
}
frame, err := (Encoder{}).DataFrame(CommandRealtime, "LTEST32960VIN0001", at, record)
if err != nil {
t.Fatal(err)
}
env, err := gb32960.ParseFrame(frame, at.UnixMilli(), "test")
if err != nil {
t.Fatal(err)
}
if env.MessageID != "0x02" || env.VIN != "LTEST32960VIN0001" {
t.Fatalf("unexpected envelope: %#v", env)
}
if got := env.Fields["speed_kmh"]; got != 42.3 {
t.Fatalf("speed = %#v", got)
}
if got := env.Fields["total_mileage_km"]; got != 12345.6 {
t.Fatalf("mileage = %#v", got)
}
if got := env.Fields["soc_percent"]; got != 78 {
t.Fatalf("soc = %#v", got)
}
if got := env.Fields["longitude"]; got != 113.2644 {
t.Fatalf("longitude = %#v", got)
}
if _, exists := env.Fields["gd_fc_vehicle_hydrogen_mass_kg"]; exists {
t.Fatal("bridge must not derive hydrogen mass from platform percentage")
}
}
func TestDataFrameSplitsMoreThan255CellVoltages(t *testing.T) {
values := make([]string, 288)
for index := range values {
values[index] = fmt.Sprintf("%.3f", 3.5+float64(index)/1000)
}
frame, err := (Encoder{}).DataFrame(CommandReissue, "LTEST32960VIN0002", time.Now(), Record{
"2003": "1:" + strings.Join(values, "_"),
"2613": "530",
"2614": "10",
})
if err != nil {
t.Fatal(err)
}
body := frame[24 : len(frame)-1]
if got := strings.Count(string(body), string([]byte{0x08})); got < 2 {
t.Fatalf("expected at least two voltage units, got %d", got)
}
if binary.BigEndian.Uint16(frame[22:24]) != uint16(len(body)) {
t.Fatal("body length mismatch")
}
if _, err := gb32960.ParseFrame(frame, time.Now().UnixMilli(), "test"); err != nil {
t.Fatal(err)
}
}
func TestLoginFrameLayout(t *testing.T) {
frame, err := LoginFrame("FEICHIBRIDGE00001", "bridge", "secret", 7, time.Date(2026, 7, 17, 1, 2, 3, 0, shanghai))
if err != nil {
t.Fatal(err)
}
if frame[2] != CommandLogin || frame[3] != 0xFE {
t.Fatalf("unexpected login header: %x", frame[:4])
}
if got := binary.BigEndian.Uint16(frame[30:32]); got != 7 {
t.Fatalf("serial = %d", got)
}
if got, want := frame[len(frame)-1], bcc(frame[2:len(frame)-1]); got != want {
t.Fatalf("BCC = %x, want %x", got, want)
}
}