package extract import ( "bufio" "encoding/binary" "errors" "fmt" "os" "path/filepath" "sort" "strings" "time" "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus" ) // 每行传感器数据帧头信息长度为24字节 type AuxFrameHead struct { PkgHead [4]byte // 包头头标识符,固定为0xD15BD15B FillByte0 byte // 填充字节 0x00 FrmHead [6]byte // 帧头标识符,固定为0xEB90EB90EB90 // 图像模式 // B7 模式标识 000:为线阵模式 // B6 // B5 // B4 B4谱状态 0:不输出1:输出 // B3 B3谱状态 0:不输出1:输出 // B2 B2谱状态 0:不输出1:输出 // B1 B1谱状态 0:不输出1:输出 // B0 全色状态 0:不输出1:输出 ImgMode byte SerialNo uint32 // 当前流水号 TimeSec uint32 // 时间(秒) 量纲:1us/bit,十六进制无符号整型数 TimeSecFrac uint32 // 秒小数 FileNo uint8 // 文件号 IsValidFrmHead bool B0 bool B1 bool B2 bool B3 bool B4 bool IsLinerMatrix bool RowLength int } func (afh *AuxFrameHead) Decode(data []byte) error { if len(data) < 24 { return errors.New("length of AuxFrameHead is not 24") } afh.PkgHead = [4]byte{data[0], data[1], data[2], data[3]} afh.FillByte0 = data[4] afh.FrmHead = [6]byte{data[5], data[6], data[7], data[8], data[9], data[10]} afh.ImgMode = data[11] afh.B0 = (afh.ImgMode&(1<<0) != 0x0) afh.B1 = (afh.ImgMode&(1<<1) != 0x0) afh.B2 = (afh.ImgMode&(1<<2) != 0x0) afh.B3 = (afh.ImgMode&(1<<3) != 0x0) afh.B4 = (afh.ImgMode&(1<<4) != 0x0) afh.IsLinerMatrix = (afh.ImgMode&(1<<5) == 0x0 && afh.ImgMode&(1<<6) == 0x0 && afh.ImgMode&(1<<7) == 0x0) afh.SerialNo = binary.BigEndian.Uint32(data[12:16]) afh.TimeSec = binary.BigEndian.Uint32(data[16:20]) afh.TimeSecFrac = uint32(uint32(data[20])<<16 | uint32(data[21])<<8 | uint32(data[22])) //binary.BigEndian.Uint32(data[20:23]) afh.FileNo = data[23] afh.RowLength = afh.LengthOfRow() afh.IsValidFrmHead = afh.CheckFrmHead() return nil } // 计算一行数据长度:帧头+辅助数据+图像数据 func (afh AuxFrameHead) LengthOfRow() int { if !afh.IsLinerMatrix { return 14344 } length := 64 // 帧头+辅助数据长度 if afh.B0 { length += 19040 } if afh.B1 { length += 1192 } if afh.B2 { length += 1192 } if afh.B3 { length += 1192 } if afh.B4 { length += 1192 } return length } func (afh AuxFrameHead) CheckFrmHead() bool { if afh.FrmHead[0] == 0xEB && afh.FrmHead[1] == 0x90 && afh.FrmHead[2] == 0xEB && afh.FrmHead[3] == 0x90 && afh.FrmHead[4] == 0xEB && afh.FrmHead[5] == 0x90 { return true } return false } type Record struct { index int frmHead *AuxFrameHead } // 从传输帧文件中分离辅助数据,分别存储到辅助数据文件 _AUX.dat 和图像数据文件 _IMG_{波谱}.dat 中 func (p *Extractor) SeprateAuxAndImgData(sDataFile string) error { // 打开传输帧文件 - 一次读入内存 sData, err := os.ReadFile(sDataFile) if err != nil { log.Println("read data from", sDataFile, "error:", err.Error()) return err } log.Info("seprate aux and img data from", sDataFile) // 数据质量分析 fimg, _ := os.Create("demo/temp/aux_img.txt") defer fimg.Close() fimg.WriteString("字节数 帧头流水号 文件号 帧头时间 中心辅助数据前4字节(行33-36)\n") var qmap []*Record for i := 0; i < len(sData); { // 解析帧 if i+24 > len(sData) { log.Info("length of frame head is not engough for frame head") break } if sData[i] == 0xD1 && sData[i+1] == 0x5B && sData[i+2] == 0xD1 && sData[i+3] == 0x5B { log.Debug("find package head: 0xD15BD15B") } else { i++ // log.Println(i,"not find package head: 0xD15BD15B, skip 1 byte") continue } afh := &AuxFrameHead{} afh.Decode(sData[i : i+24]) if !afh.IsValidFrmHead { log.Info("invalid frame head of original raw data", afh.FrmHead, "i =", i) i += 1 } else { r := &Record{index: i, frmHead: afh} qmap = append(qmap, r) i += 24 // fmt.Println("sn:", afh.SerialNo, "time:", afh.TimeSec) // fmt.Println(time.Unix(int64(afh.TimeSec+uint32(ReferenceTime2000)), 0).String()) utcTime := binary.BigEndian.Uint32(sData[i+32 : i+36]) // fmt.Println("utc time of platform aux:", utcTime) // fmt.Println(time.Unix(int64(utcTime), 0).String()) // fmt.Println("waveway:", sData[i+36]) t := time.Unix(int64(afh.TimeSec+uint32(ReferenceTime2000)), 0) tAux := time.Unix(int64(utcTime), 0) fimg.WriteString(fmt.Sprintf("%d %d %d %s %s\n", i, afh.SerialNo, afh.FileNo, t.String(), tAux.String(), )) // if len(qmap) > 32 { // break // } } } sort.Slice(qmap, func(i, j int) bool { return qmap[i].index < qmap[j].index }) // lastPosOfPkg := 0 // lastLenOfPkg := 0 // for i, v := range qmap { // pkgLen := v.index - lastPosOfPkg // if v.index == 4112 { // fmt.Println("index 4112's frm no", i+1) // fmt.Println("last frm:", qmap[i-1].index) // fmt.Println("next frm:", qmap[i+1].index) // } // if pkgLen != 23872 { // log.Info("index:", v.index, "lastLenOfPkg:", lastLenOfPkg, "package length:", pkgLen) // } // lastLenOfPkg = pkgLen // lastPosOfPkg = v.index // } return nil name := filepath.Base(sDataFile) name = strings.TrimRight(name, filepath.Ext(name)) outputDir := p.params.OutputPath aux0 := outputDir + "/" + name + "_EB.AUX" os.Remove(aux0) faux0, _ := os.OpenFile(aux0, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0777) waux0 := bufio.NewWriter(faux0) defer waux0.Flush() defer faux0.Close() aux1 := outputDir + "/" + name + "_PLAT.AUX" os.Remove(aux1) faux1, _ := os.OpenFile(aux1, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0777) waux1 := bufio.NewWriter(faux1) defer waux1.Flush() defer faux1.Close() pan := outputDir + "/" + name + "_IMG_PAN.RAW" os.Remove(pan) fpan, _ := os.OpenFile(pan, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0777) wpan := bufio.NewWriter(fpan) defer wpan.Flush() defer fpan.Close() panEnviHdr := EnviHdr{} wpanHdr, _ := NewBSQWriter(outputDir+"/"+name+"_IMG_PAN.HDR", &panEnviHdr) defer wpanHdr.Close() // 先按单波段存储,再按波段组合存储为 BSQ 格式的 MSS mss := outputDir + "/" + name + "_IMG_MSS.RAW" os.Remove(mss) fmss, _ := os.OpenFile(mss, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0777) wmss := bufio.NewWriter(fmss) defer wmss.Flush() defer fmss.Close() mssEnviHdr := EnviHdr{} wmssHdr, _ := NewBSQWriter(outputDir+"/"+name+"_IMG_MSS.HDR", &mssEnviHdr) defer wmssHdr.Close() var afh AuxFrameHead dataLen := len(sData) for i := 0; i < dataLen; { if i+4 > dataLen { logrus.Println("end of data, dataLen:", dataLen, "i:", i) break } // 包头 if sData[i] == 0xD1 && sData[i+1] == 0x5B && sData[i+2] == 0xD1 && sData[i+3] == 0x5B { log.Debug("find package head: 0xD15BD15B") } else { i++ // log.Println("not find package head: 0xD15BD15B, skip 1 byte") continue } // 解析帧 if i+24 > dataLen { log.Info("length of frame head is not engough for frame head") break } afh.Decode(sData[i : i+24]) // pp.Println(afh) if !afh.IsValidFrmHead { log.Info("invalid frame head of original raw data") i += 1 continue } // 目前只支持线阵模式 if !afh.IsLinerMatrix { log.Error("not liner matrix mode, only support liner matrix mode") break } // 读取一行数据 sData[i : i+afh.RowLength] if i+afh.RowLength > dataLen { log.Info("length of row data is not enough for row length:", afh.RowLength) break } // 存储辅助数据到临时文件 dataIndex := i + 24 waux0.Write(sData[dataIndex : dataIndex+8]) // 8字节焦面电箱辅助数据 dataIndex += 8 waux1.Write(sData[dataIndex : dataIndex+32]) // 32字节中心机辅助数据 dataIndex += 32 // 存储图像数据到临时文件 - 以 ENVI BSQ 格式存储,同时提供 HDR 描述文件 if afh.B0 { wpan.Write(sData[dataIndex : dataIndex+19040]) dataIndex += 19040 panEnviHdr.Lines += 1 } if afh.B1 { wmss.Write(sData[dataIndex : dataIndex+1192]) dataIndex += 1192 mssEnviHdr.Lines += 1 } if afh.B2 { wmss.Write(sData[dataIndex : dataIndex+1192]) dataIndex += 1192 } if afh.B3 { wmss.Write(sData[dataIndex : dataIndex+1192]) dataIndex += 1192 } if afh.B4 { wmss.Write(sData[dataIndex : dataIndex+1192]) dataIndex += 1192 } i = dataIndex // 完成一行数据解析 } panEnviHdr.Samples = 9520 panEnviHdr.Bands = 1 wpanHdr.Write([]byte(panEnviHdr.String())) mssEnviHdr.Lines = mssEnviHdr.Lines / 4 // 多光谱波段分别在 4 行中传输 mssEnviHdr.Bands = 1 mssEnviHdr.Samples = 2384 * 4 wmssHdr.Write([]byte(mssEnviHdr.String())) return nil }