kopia lustrzana https://github.com/cyoung/stratux
Replaced NEXRAD processing.
rodzic
386be11b8c
commit
b829e2228a
|
@ -0,0 +1,147 @@
|
|||
package uatparse
|
||||
|
||||
import ()
|
||||
|
||||
const (
|
||||
BLOCK_WIDTH = float64(48.0 / 60.0)
|
||||
WIDE_BLOCK_WIDTH = float64(96.0 / 60.0)
|
||||
BLOCK_HEIGHT = float64(4.0 / 60.0)
|
||||
BLOCK_THRESHOLD = 405000
|
||||
BLOCKS_PER_RING = 450
|
||||
)
|
||||
|
||||
type NEXRADBlock struct {
|
||||
radar_type uint32
|
||||
scale int
|
||||
latNorth float64
|
||||
lonWest float64
|
||||
height float64
|
||||
width float64
|
||||
intensity []uint8 // Really only 4-bit values.
|
||||
}
|
||||
|
||||
func block_location(block_num int, ns_flag bool, scale_factor int) (float64, float64, float64, float64) {
|
||||
var realScale float64
|
||||
if scale_factor == 1 {
|
||||
realScale = float64(5.0)
|
||||
} else if scale_factor == 2 {
|
||||
realScale = float64(9.0)
|
||||
} else {
|
||||
realScale = float64(1.0)
|
||||
}
|
||||
|
||||
if block_num >= BLOCK_THRESHOLD {
|
||||
block_num = block_num & ^1
|
||||
}
|
||||
|
||||
raw_lat := float64(BLOCK_HEIGHT * float64(int(float64(block_num)/float64(BLOCKS_PER_RING))))
|
||||
raw_lon := float64(block_num%BLOCKS_PER_RING) * BLOCK_WIDTH
|
||||
|
||||
var lonSize float64
|
||||
if block_num >= BLOCK_THRESHOLD {
|
||||
lonSize = WIDE_BLOCK_WIDTH * realScale
|
||||
} else {
|
||||
lonSize = BLOCK_WIDTH * realScale
|
||||
}
|
||||
|
||||
latSize := BLOCK_HEIGHT * realScale
|
||||
|
||||
if ns_flag { // Southern hemisphere.
|
||||
raw_lat = 0 - raw_lat
|
||||
} else {
|
||||
raw_lat = raw_lat + BLOCK_HEIGHT
|
||||
}
|
||||
|
||||
if raw_lon > 180.0 {
|
||||
raw_lon = raw_lon - 360.0
|
||||
}
|
||||
|
||||
return raw_lat, raw_lon, latSize, lonSize
|
||||
|
||||
}
|
||||
|
||||
func (f *UATFrame) decodeNexradFrame() {
|
||||
if len(f.FISB_data) < 4 { // Short read.
|
||||
return
|
||||
}
|
||||
|
||||
rle_flag := (uint32(f.FISB_data[0]) & 0x80) != 0
|
||||
ns_flag := (uint32(f.FISB_data[0]) & 0x40) != 0
|
||||
block_num := ((int(f.FISB_data[0]) & 0x0f) << 16) | (int(f.FISB_data[1]) << 8) | (int(f.FISB_data[2]))
|
||||
scale_factor := (int(f.FISB_data[0]) & 0x30) >> 4
|
||||
|
||||
if rle_flag { // Single bin, RLE encoded.
|
||||
lat, lon, h, w := block_location(block_num, ns_flag, scale_factor)
|
||||
var tmp NEXRADBlock
|
||||
tmp.radar_type = f.Product_id
|
||||
tmp.scale = scale_factor
|
||||
tmp.latNorth = lat
|
||||
tmp.lonWest = lon
|
||||
tmp.height = h
|
||||
tmp.width = w
|
||||
tmp.intensity = make([]uint8, 0)
|
||||
|
||||
intensityData := f.FISB_data[3:]
|
||||
for _, v := range intensityData {
|
||||
intensity := uint8(v) & 0x7
|
||||
runlength := (uint8(v) >> 3) + 1
|
||||
for runlength > 0 {
|
||||
tmp.intensity = append(tmp.intensity, intensity)
|
||||
runlength--
|
||||
}
|
||||
}
|
||||
f.NEXRAD = []NEXRADBlock{tmp}
|
||||
} else {
|
||||
var row_start int
|
||||
var row_size int
|
||||
if block_num >= 405000 {
|
||||
row_start = block_num - ((block_num - 405000) % 225)
|
||||
row_size = 225
|
||||
} else {
|
||||
row_start = block_num - (block_num % 450)
|
||||
row_size = 450
|
||||
}
|
||||
|
||||
row_offset := block_num - row_start
|
||||
|
||||
L := int(f.FISB_data[3] & 15)
|
||||
|
||||
if len(f.FISB_data) < L+3 { // Short read.
|
||||
return
|
||||
}
|
||||
|
||||
for i := 0; i < L; i++ {
|
||||
var bb int
|
||||
if i == 0 {
|
||||
bb = (int(f.FISB_data[3]) & 0xF0) | 0x08
|
||||
} else {
|
||||
bb = int(f.FISB_data[i+3])
|
||||
}
|
||||
|
||||
for j := 0; j < 8; j++ {
|
||||
if bb&(1<<uint(j)) != 0 {
|
||||
row_x := (row_offset + 8*i + j - 3) % row_size
|
||||
bn := row_start + row_x
|
||||
lat, lon, h, w := block_location(bn, ns_flag, scale_factor)
|
||||
var tmp NEXRADBlock
|
||||
tmp.radar_type = f.Product_id
|
||||
tmp.scale = scale_factor
|
||||
tmp.latNorth = lat
|
||||
tmp.lonWest = lon
|
||||
tmp.height = h
|
||||
tmp.width = w
|
||||
tmp.intensity = make([]uint8, 0)
|
||||
for k := 0; k < 128; k++ {
|
||||
z := uint8(0)
|
||||
if f.Product_id == 64 {
|
||||
z = 1
|
||||
}
|
||||
tmp.intensity = append(tmp.intensity, z)
|
||||
}
|
||||
f.NEXRAD = append(f.NEXRAD, tmp)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
|
@ -10,8 +10,6 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
var elementIdentifier byte
|
||||
|
||||
const (
|
||||
UPLINK_BLOCK_DATA_BITS = 576
|
||||
UPLINK_BLOCK_BITS = (UPLINK_BLOCK_DATA_BITS + 160)
|
||||
|
@ -27,8 +25,6 @@ const (
|
|||
// assume 6 byte frames: 2 header bytes, 4 byte payload
|
||||
// (TIS-B heartbeat with one address, or empty FIS-B APDU)
|
||||
UPLINK_MAX_INFO_FRAMES = (424 / 6)
|
||||
COLS_PER_BIN = 32
|
||||
ROWS_PER_BIN = 4
|
||||
|
||||
dlac_alpha = "\x03ABCDEFGHIJKLMNOPQRSTUVWXYZ\x1A\t\x1E\n| !\"#$%&'()*+,-./0123456789:;<=>?"
|
||||
)
|
||||
|
@ -66,6 +62,9 @@ type UATFrame struct {
|
|||
RecordFormat uint8
|
||||
ReportStart string
|
||||
ReportEnd string
|
||||
|
||||
// For NEXRAD.
|
||||
NEXRAD []NEXRADBlock
|
||||
}
|
||||
|
||||
type UATMsg struct {
|
||||
|
@ -192,123 +191,6 @@ func formatDLACData(p string) []string {
|
|||
return ret
|
||||
}
|
||||
|
||||
func (f *UATFrame) decodeNexradFrame() {
|
||||
ret := make([]string, 0)
|
||||
builder := make([]string, 0)
|
||||
|
||||
if len(f.FISB_data) < int(f.FISB_length) {
|
||||
return
|
||||
}
|
||||
mEmpty := make([]int32, 1)
|
||||
mData := make([]int32, COLS_PER_BIN*ROWS_PER_BIN)
|
||||
elementIdentifier := f.FISB_data[0] & 0x80
|
||||
mBlock := uint32(f.FISB_data[0]&0x0f) << 16
|
||||
mBlock = mBlock | uint32(f.FISB_data[1])<<8
|
||||
mBlock = mBlock | uint32(f.FISB_data[2])
|
||||
index := 3
|
||||
// Make 32 * 4 array
|
||||
if elementIdentifier != 0 {
|
||||
// Clear the array
|
||||
for c := 0; c < (COLS_PER_BIN * ROWS_PER_BIN); c++ {
|
||||
mData[c] = 0
|
||||
}
|
||||
j := 0
|
||||
for index < int(f.FISB_length) {
|
||||
numberOfBins := ((f.FISB_data[index] & 0xf8) >> 3) + 1
|
||||
for i := 0; i < int(numberOfBins); i++ {
|
||||
if j >= int(COLS_PER_BIN*ROWS_PER_BIN) {
|
||||
return
|
||||
}
|
||||
mData[j] = int32(f.FISB_data[index] & 0x07)
|
||||
j++
|
||||
}
|
||||
index++
|
||||
}
|
||||
} else {
|
||||
bitmapLen := int32(f.FISB_data[index] & 0x0f)
|
||||
// Start with 1 element
|
||||
|
||||
mEmpty[0] = int32(mBlock)
|
||||
if (f.FISB_data[index] & 0x10) != 0 {
|
||||
mEmpty = append(mEmpty, int32(mBlock+1))
|
||||
}
|
||||
if (f.FISB_data[index] & 0x20) != 0 {
|
||||
mEmpty = append(mEmpty, int32(mBlock+2))
|
||||
}
|
||||
if (f.FISB_data[index] & 0x30) != 0 {
|
||||
mEmpty = append(mEmpty, int32(mBlock+3))
|
||||
}
|
||||
if (f.FISB_data[index] & 0x40) != 0 {
|
||||
mEmpty = append(mEmpty, int32(mBlock+4))
|
||||
}
|
||||
for i := 1; i < int(bitmapLen); i++ {
|
||||
if (f.FISB_data[index+i] & 0x01) != 0 {
|
||||
mEmpty = append(mEmpty, int32(mBlock+uint32(i)*8-3))
|
||||
}
|
||||
if (f.FISB_data[index+i] & 0x02) != 0 {
|
||||
mEmpty = append(mEmpty, int32(mBlock+uint32(i)*8-2))
|
||||
}
|
||||
if (f.FISB_data[index+i] & 0x04) != 0 {
|
||||
mEmpty = append(mEmpty, int32(mBlock+uint32(i)*8-1))
|
||||
}
|
||||
if (f.FISB_data[index+i] & 0x08) != 0 {
|
||||
mEmpty = append(mEmpty, int32(mBlock+uint32(i)*8-0))
|
||||
}
|
||||
if (f.FISB_data[index+i] & 0x10) != 0 {
|
||||
mEmpty = append(mEmpty, int32(mBlock+uint32(i)*8+1))
|
||||
}
|
||||
if (f.FISB_data[index+i] & 0x20) != 0 {
|
||||
mEmpty = append(mEmpty, int32(mBlock+uint32(i)*8+2))
|
||||
}
|
||||
if (f.FISB_data[index+i] & 0x40) != 0 {
|
||||
mEmpty = append(mEmpty, int32(mBlock+uint32(i)*8+3))
|
||||
}
|
||||
if (f.FISB_data[index+i] & 0x80) != 0 {
|
||||
mEmpty = append(mEmpty, int32(mBlock+uint32(i)*8+4))
|
||||
}
|
||||
}
|
||||
}
|
||||
log.Printf("NEXRAD: elementIdentifier %d mBlock %d\n", elementIdentifier, mBlock)
|
||||
log.Printf("NEXRAD: mEmpty %d mData %d\n", mEmpty, mData)
|
||||
// field 1 - NEXRAD
|
||||
builder = append(builder, "NEXRAD")
|
||||
// CONUS
|
||||
if f.Product_id == 63 {
|
||||
builder = append(builder, "0")
|
||||
} else {
|
||||
builder = append(builder, "1")
|
||||
}
|
||||
// Field 3 block
|
||||
builder = append(builder, fmt.Sprintf("%d", mBlock))
|
||||
// Field 4 Columns
|
||||
builder = append(builder, fmt.Sprintf("%d", COLS_PER_BIN))
|
||||
// Field 5 Rows
|
||||
builder = append(builder, fmt.Sprintf("%d", ROWS_PER_BIN))
|
||||
if elementIdentifier != 0 {
|
||||
builder = append(builder, "1")
|
||||
bin := ""
|
||||
for br := range mData {
|
||||
bin = bin + fmt.Sprintf("%d,", mData[br])
|
||||
}
|
||||
if bin[len(bin)-1] == ',' {
|
||||
bin = bin[0 : len(bin)-1]
|
||||
}
|
||||
builder = append(builder, bin)
|
||||
} else {
|
||||
builder = append(builder, "0")
|
||||
bin2 := ""
|
||||
for be := range mEmpty {
|
||||
bin2 = bin2 + fmt.Sprintf("%d,", mEmpty[be])
|
||||
}
|
||||
if bin2[len(bin2)-1] == ',' {
|
||||
bin2 = bin2[0 : len(bin2)-1]
|
||||
}
|
||||
builder = append(builder, bin2)
|
||||
}
|
||||
ret = append(ret, fmt.Sprintf(strings.Join(builder, " ")))
|
||||
f.Text_data = ret
|
||||
}
|
||||
|
||||
// Whole frame contents is DLAC encoded text.
|
||||
func (f *UATFrame) decodeTextFrame() {
|
||||
if len(f.FISB_data) < int(f.FISB_length) {
|
||||
|
|
Ładowanie…
Reference in New Issue