go-comtrade/binary_data.go

113 lines
3.4 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package comtrade
import (
"encoding/binary"
"math"
"os"
)
// BinaryData is the binary data of a comtrade data file
func init() {
Add(TypeBinary, func() Parser {
return &BinaryData{}
})
}
// 读取数据文件
// 1、采样序号和时标均以四字节无符号二进制格式存储
// 2、模拟通道采样数据binary两个字节binary32四个字节二进制补码形式存储
// 3、每16个状态通道以两个字节一组存储字的最低为对应该组16个状态通道中最小编号通道
// 4、每次采样字节数=(模拟通道数 * 每个采样数据占据字节数)+(状态通道数 / 16 * 2 + 4 + 4
// 5、每个采样数据占据字节数=2或4取决于数据格式2表示binary4表示binary32
// 05667-76012747261-140-502000011
// 05 00 00 00
// 9B 02 00 00 667
// 08 FD -760
// FA 04 1274
// 48 00 72
// 3D 00 61
// 74 FF -140
// 0A FE -502
// 30 00 000011
type BinaryData struct{}
func (b *BinaryData) Parse(filePath string, analogNum, digitalNum, endSamp uint32) (*Data, error) {
comtradeData := &Data{}
// 打开文件
file, err := os.Open(filePath)
if err != nil {
return nil, err
}
defer file.Close()
comtradeData.AnalogData = make([]AnalogData, int(endSamp))
comtradeData.DigitalData = make([]DigitalData, int(endSamp))
for i := 0; i < int(endSamp); i++ {
comtradeData.AnalogData[i].Data = make([]int32, analogNum)
comtradeData.DigitalData[i].Data = make([]uint8, digitalNum)
}
// 计算状态通道组数
digitalCount := int(math.Ceil(float64(digitalNum) / 16.0))
remainder := int(digitalNum % 16)
for i := 0; i < int(endSamp); i++ {
var (
sampleIndex uint32
timestamp uint32
)
// 解析采样序号
if err := binary.Read(file, binary.LittleEndian, &sampleIndex); err != nil {
return nil, err
}
comtradeData.AnalogData[i].N = sampleIndex
comtradeData.DigitalData[i].N = sampleIndex
// 解析采样时标
if err = binary.Read(file, binary.LittleEndian, &timestamp); err != nil {
return nil, err
}
comtradeData.AnalogData[i].Timestamp = timestamp
comtradeData.DigitalData[i].Timestamp = timestamp
// 解析模拟通道采样数据
for m := 0; m < int(analogNum); m++ {
var tmp int16
if err := binary.Read(file, binary.LittleEndian, &tmp); err != nil {
return nil, err
} else {
comtradeData.AnalogData[i].Data[m] = int32(tmp)
}
}
// 3、每16个状态通道以两个字节一组存储字的最低为对应该组16个状态通道中最小编号通道
// 4、每次采样字节数=(模拟通道数 * 每个采样数据占据字节数)+(状态通道数 / 16 * 2 + 4 + 4
// 5、每个采样数据占据字节数=2或4取决于数据格式2表示binary4表示binary32
stateData := make([]uint16, digitalCount)
for n, datum := range stateData {
data := datum
if err := binary.Read(file, binary.LittleEndian, &data); err != nil {
return nil, err
}
stateData[n] = data
}
for h, datum := range stateData {
if remainder != 0 && h == digitalCount-1 {
for j := 0; j < remainder; j++ {
comtradeData.DigitalData[i].Data[(h*16)+j] = uint8(uint((datum >> uint(j)) & 0x0001))
}
break
}
for k := 0; k < 16; k++ {
comtradeData.DigitalData[i].Data[(h*16)+k] = uint8(uint((datum >> uint(k)) & 0x0001))
}
}
}
return comtradeData, nil
}