package m9z import ( "encoding/binary" "fmt" "github.com/gogf/gf/v2/errors/gerror" "math" "time" ) type LgnLatData struct { Lgn float64 // 经度 Lat float64 // 纬度 Loc *time.Location } // 经纬度参数 func LgnLatRead(deviceId string) (*LgnLatData, error) { ll := new(LgnLatData) cmd, err := ReadCmd(deviceId, lgnLat, "读取经纬度参数") if err != nil { return nil, err } data := cmd.Data lgn := float64(binary.LittleEndian.Uint32(data[0:4])) / 1000000 lat := float64(binary.LittleEndian.Uint32(data[4:8])) / 1000000 loc := float64(binary.LittleEndian.Uint32(data[8:len(data)])) / 1000000 ll.Lgn = lgn ll.Lat = lat timezone, err := FloatToTimezone(loc) if err != nil { return nil, err } ll.Loc = timezone return ll, nil } func LgnLatWrite(deviceId string, data *LgnLatData) error { // 将浮点型经纬度转换为字节编码(兼容原Read逻辑) buf := make([]byte, 12) // 1. 处理经度(4字节) lgnInt := uint32(math.Round(data.Lgn * 1000000)) binary.LittleEndian.PutUint32(buf[0:4], lgnInt) // 2. 处理纬度(4字节) latInt := uint32(math.Round(data.Lat * 1000000)) binary.LittleEndian.PutUint32(buf[4:8], latInt) // 3. 处理时区(4字节) // 从time.Location解析出UTC偏移小时数(含小数) offsetHours, err := getTimezoneOffset(data.Loc) if err != nil { return err } offsetInt := uint32(math.Round(offsetHours * 1000000)) binary.LittleEndian.PutUint32(buf[8:12], offsetInt) writeResp, err := WriteCmd(deviceId, lgnLat, buf, "写入经纬度参数") if err != nil { return err } if !writeResp.Success { return gerror.New("设置失败") } return nil } // 从time.Location中解析UTC偏移小时数(支持正负) func getTimezoneOffset(loc *time.Location) (float64, error) { // 任取一个时间点计算偏移(固定时区偏移不会变化) t := time.Date(2023, 1, 1, 0, 0, 0, 0, loc) _, offsetSec := t.Zone() // 转换为小时(含小数) offsetHours := float64(offsetSec) / 3600.0 if offsetHours < -12 || offsetHours > 14 { return 0, fmt.Errorf("invalid timezone offset: %f", offsetHours) } return offsetHours, nil } // FloatToTimezone 将float64时区值转换为 *time.Location // 输入示例: 8.0 → UTC+8, -5.5 → UTC-5:30 func FloatToTimezone(offset float64) (*time.Location, error) { // 验证范围 (-12.0 到 +14.0) if offset < -12.0 || offset > 14.0 { return nil, fmt.Errorf("时区偏移量超出有效范围 (-12.0 到 +14.0)") } // 分解小时和分钟 hours := int(math.Floor(offset)) minutes := int(math.Round((offset - float64(hours)) * 60)) // 处理负数情况 if offset < 0 { minutes = -minutes } // 创建固定时区 name := fmt.Sprintf("UTC%+03d:%02d", hours, minutes) return time.FixedZone(name, hours*3600+minutes*60), nil }