package gps import ( "testing" ) func TestCfgNav5ClassID(t *testing.T) { cfg := CfgNav5{} if got := cfg.classID(); got != 0x2406 { t.Errorf("expected 0x2406, got 0x%04x", got) } } func TestCfgNav5Write(t *testing.T) { cfg := CfgNav5{ Mask: CfgNav5Dyn | CfgNav5MinEl, DynModel: 4, FixMode: 3, FixedAlt_me2: 10000, FixedAltVar_m2e4: 10000, MinElev_deg: 5, DrLimit_s: 0, PDop: 250, TDop: 250, PAcc_m: 100, TAcc_m: 300, StaticHoldThresh_cm_s: 50, DgnssTimeout_s: 60, CnoThreshNumSVs: 3, CnoThresh_dbhz: 35, Reserved1: [2]byte{0, 0}, StaticHoldMaxDist_m: 200, UtcStandard: 0, Reserved2: [5]byte{0, 0, 0, 0, 0}, } buf := make([]byte, 64) cfg.Put42Bytes(buf) // Check sync chars if buf[0] != 0xb5 || buf[1] != 0x62 { t.Errorf("expected sync chars 0xb5 0x62, got 0x%02x 0x%02x", buf[0], buf[1]) } // Check class/id (little-endian) if buf[2] != 0x06 || buf[3] != 0x24 { t.Errorf("expected class/id 0x06 0x24, got 0x%02x 0x%02x", buf[2], buf[3]) } // Check length if buf[4] != 36 || buf[5] != 0 { t.Errorf("expected length 36, got %d", uint16(buf[4])|uint16(buf[5])<<8) } // Check Mask (little-endian) mask := uint16(buf[6]) | uint16(buf[7])<<8 if mask != uint16(CfgNav5Dyn|CfgNav5MinEl) { t.Errorf("expected mask 0x03, got 0x%04x", mask) } // Check DynModel if buf[8] != 4 { t.Errorf("expected DynModel 4, got %d", buf[8]) } // Check FixMode if buf[9] != 3 { t.Errorf("expected FixMode 3, got %d", buf[9]) } // Check FixedAlt_me2 (little-endian int32) fixedAlt := int32(buf[10]) | int32(buf[11])<<8 | int32(buf[12])<<16 | int32(buf[13])<<24 if fixedAlt != 10000 { t.Errorf("expected FixedAlt_me2 10000, got %d", fixedAlt) } } func TestCfgGnssClassID(t *testing.T) { cfg := CfgGnss{} if got := cfg.classID(); got != 0x3e06 { t.Errorf("expected 0x3e06, got 0x%04x", got) } } func TestCfgGnssWrite(t *testing.T) { testCases := []struct { name string cfg CfgGnss expectedLen int expectedBlocks byte }{ { name: "no config blocks", cfg: CfgGnss{ MsgVer: 0, NumTrkChHw: 32, NumTrkChUse: 32, ConfigBlocks: nil, }, expectedLen: 10, expectedBlocks: 0, }, { name: "one config block", cfg: CfgGnss{ MsgVer: 0, NumTrkChHw: 32, NumTrkChUse: 32, ConfigBlocks: []CfgGnssConfigBlocksType{ {GnssId: 0, ResTrkCh: 8, MaxTrkCh: 16, Flags: CfgGnssEnable | 0x010000}, }, }, expectedLen: 18, expectedBlocks: 1, }, { name: "two config blocks", cfg: CfgGnss{ MsgVer: 0, NumTrkChHw: 32, NumTrkChUse: 32, ConfigBlocks: []CfgGnssConfigBlocksType{ {GnssId: 0, ResTrkCh: 8, MaxTrkCh: 16, Flags: CfgGnssEnable | 0x010000}, {GnssId: 6, ResTrkCh: 8, MaxTrkCh: 14, Flags: CfgGnssEnable | 0x010000}, }, }, expectedLen: 26, expectedBlocks: 2, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { buf := make([]byte, 64) err := tc.cfg.Put(buf) if err != nil { t.Errorf("unexpected error, data too long?: %v", err) } // Check sync chars if buf[0] != 0xb5 || buf[1] != 0x62 { t.Errorf("expected sync chars 0xb5 0x62, got 0x%02x 0x%02x", buf[0], buf[1]) } // Check class/id (little-endian) if buf[2] != 0x06 || buf[3] != 0x3e { t.Errorf("expected class/id 0x06 0x3e, got 0x%02x 0x%02x", buf[2], buf[3]) } // Check number of config blocks if buf[9] != tc.expectedBlocks { t.Errorf("expected %d config blocks, got %d", tc.expectedBlocks, buf[9]) } }) } } func TestCfgGnssWriteBlockContent(t *testing.T) { cfg := CfgGnss{ MsgVer: 0, NumTrkChHw: 32, NumTrkChUse: 32, ConfigBlocks: []CfgGnssConfigBlocksType{ {GnssId: 0, ResTrkCh: 8, MaxTrkCh: 16, Reserved1: 0, Flags: CfgGnssEnable | 0x010000}, }, } buf := make([]byte, 64) err := cfg.Put(buf) if err != nil { t.Fatal(err) } // Check first block at offset 10 if buf[10] != 0 { t.Errorf("expected GnssId 0, got %d", buf[10]) } if buf[11] != 8 { t.Errorf("expected ResTrkCh 8, got %d", buf[11]) } if buf[12] != 16 { t.Errorf("expected MaxTrkCh 16, got %d", buf[12]) } // Check flags (little-endian uint32) flags := uint32(buf[14]) | uint32(buf[15])<<8 | uint32(buf[16])<<16 | uint32(buf[17])<<24 expectedFlags := uint32(CfgGnssEnable | 0x010000) if flags != expectedFlags { t.Errorf("expected flags 0x%08x, got 0x%08x", expectedFlags, flags) } }