97 lines
3.0 KiB
Go
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)
|
|
}
|
|
}
|