kopia lustrzana https://github.com/cyoung/stratux
commit
c4762633b0
|
@ -1,31 +1,29 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
|
||||||
"fmt"
|
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
"sync"
|
"sync"
|
||||||
"github.com/sevlyar/go-daemon"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ipadAddr = "192.168.10.255:49002"
|
ipadAddr = "192.168.10.255:49002"
|
||||||
dump1090Addr = "127.0.0.1:30003"
|
dump1090Addr = "127.0.0.1:30003"
|
||||||
maxDatagramSize = 8192
|
maxDatagramSize = 8192
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
type PositionInfo struct {
|
type PositionInfo struct {
|
||||||
lat string
|
lat string
|
||||||
lng string
|
lng string
|
||||||
alt string
|
alt string
|
||||||
hdg string
|
hdg string
|
||||||
vel string
|
vel string
|
||||||
vr string
|
vr string
|
||||||
tail string
|
tail string
|
||||||
last_seen time.Time
|
last_seen time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,31 +1,30 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
|
||||||
"fmt"
|
|
||||||
"bufio"
|
"bufio"
|
||||||
"strings"
|
|
||||||
"encoding/hex"
|
|
||||||
"log"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
UPLINK_BLOCK_DATA_BITS = 576
|
UPLINK_BLOCK_DATA_BITS = 576
|
||||||
UPLINK_BLOCK_BITS = (UPLINK_BLOCK_DATA_BITS+160)
|
UPLINK_BLOCK_BITS = (UPLINK_BLOCK_DATA_BITS + 160)
|
||||||
UPLINK_BLOCK_DATA_BYTES = (UPLINK_BLOCK_DATA_BITS/8)
|
UPLINK_BLOCK_DATA_BYTES = (UPLINK_BLOCK_DATA_BITS / 8)
|
||||||
UPLINK_BLOCK_BYTES = (UPLINK_BLOCK_BITS/8)
|
UPLINK_BLOCK_BYTES = (UPLINK_BLOCK_BITS / 8)
|
||||||
|
|
||||||
UPLINK_FRAME_BLOCKS = 6
|
UPLINK_FRAME_BLOCKS = 6
|
||||||
UPLINK_FRAME_DATA_BITS = (UPLINK_FRAME_BLOCKS * UPLINK_BLOCK_DATA_BITS)
|
UPLINK_FRAME_DATA_BITS = (UPLINK_FRAME_BLOCKS * UPLINK_BLOCK_DATA_BITS)
|
||||||
UPLINK_FRAME_BITS = (UPLINK_FRAME_BLOCKS * UPLINK_BLOCK_BITS)
|
UPLINK_FRAME_BITS = (UPLINK_FRAME_BLOCKS * UPLINK_BLOCK_BITS)
|
||||||
UPLINK_FRAME_DATA_BYTES = (UPLINK_FRAME_DATA_BITS/8)
|
UPLINK_FRAME_DATA_BYTES = (UPLINK_FRAME_DATA_BITS / 8)
|
||||||
UPLINK_FRAME_BYTES = (UPLINK_FRAME_BITS/8)
|
UPLINK_FRAME_BYTES = (UPLINK_FRAME_BITS / 8)
|
||||||
|
|
||||||
// assume 6 byte frames: 2 header bytes, 4 byte payload
|
// assume 6 byte frames: 2 header bytes, 4 byte payload
|
||||||
// (TIS-B heartbeat with one address, or empty FIS-B APDU)
|
// (TIS-B heartbeat with one address, or empty FIS-B APDU)
|
||||||
UPLINK_MAX_INFO_FRAMES = (424/6)
|
UPLINK_MAX_INFO_FRAMES = (424 / 6)
|
||||||
|
|
||||||
dlac_alpha = "\x03ABCDEFGHIJKLMNOPQRSTUVWXYZ\x1A\t\x1E\n| !\"#$%&'()*+,-./0123456789:;<=>?"
|
dlac_alpha = "\x03ABCDEFGHIJKLMNOPQRSTUVWXYZ\x1A\t\x1E\n| !\"#$%&'()*+,-./0123456789:;<=>?"
|
||||||
)
|
)
|
||||||
|
@ -33,9 +32,8 @@ const (
|
||||||
var logger *log.Logger
|
var logger *log.Logger
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
|
||||||
|
|
||||||
func dlac_decode(data []byte, data_len uint32) string {
|
func dlac_decode(data []byte, data_len uint32) string {
|
||||||
fmt.Printf("dlac on %s\n", hex.Dump(data))
|
fmt.Printf("dlac on %s\n", hex.Dump(data))
|
||||||
step := 0
|
step := 0
|
||||||
tab := false
|
tab := false
|
||||||
ret := ""
|
ret := ""
|
||||||
|
@ -47,29 +45,29 @@ fmt.Printf("dlac on %s\n", hex.Dump(data))
|
||||||
case 1:
|
case 1:
|
||||||
ch = ((uint32(data[i-1]) & 0x03) << 4) | (uint32(data[i+0]) >> 4)
|
ch = ((uint32(data[i-1]) & 0x03) << 4) | (uint32(data[i+0]) >> 4)
|
||||||
case 2:
|
case 2:
|
||||||
ch = ((uint32(data[i-1]) & 0x0f) << 2) | (uint32(data[i+0]) >> 6);
|
ch = ((uint32(data[i-1]) & 0x0f) << 2) | (uint32(data[i+0]) >> 6)
|
||||||
i = i - 1
|
i = i - 1
|
||||||
case 3:
|
case 3:
|
||||||
ch = uint32(data[i+0]) & 0x3f
|
ch = uint32(data[i+0]) & 0x3f
|
||||||
}
|
}
|
||||||
if tab {
|
if tab {
|
||||||
for ch > 0 {
|
for ch > 0 {
|
||||||
ret += " "
|
ret += " "
|
||||||
ch--
|
ch--
|
||||||
}
|
}
|
||||||
tab = false
|
tab = false
|
||||||
} else if ch == 28 { // tab
|
} else if ch == 28 { // tab
|
||||||
tab = true
|
tab = true
|
||||||
} else {
|
} else {
|
||||||
ret += string(dlac_alpha[ch])
|
ret += string(dlac_alpha[ch])
|
||||||
}
|
}
|
||||||
step = (step+1)%4
|
step = (step + 1) % 4
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeInfoFrame(frame []byte, frame_start int, frame_len uint32, frame_type uint32) {
|
func decodeInfoFrame(frame []byte, frame_start int, frame_len uint32, frame_type uint32) {
|
||||||
data := frame[frame_start:frame_start+int(frame_len)]
|
data := frame[frame_start : frame_start+int(frame_len)]
|
||||||
|
|
||||||
if frame_type != 0 {
|
if frame_type != 0 {
|
||||||
return // Not FIS-B.
|
return // Not FIS-B.
|
||||||
|
@ -80,7 +78,7 @@ func decodeInfoFrame(frame []byte, frame_start int, frame_len uint32, frame_type
|
||||||
|
|
||||||
t_opt := ((uint32(data[1]) & 0x01) << 1) | (uint32(data[2]) >> 7)
|
t_opt := ((uint32(data[1]) & 0x01) << 1) | (uint32(data[2]) >> 7)
|
||||||
product_id := ((uint32(data[0]) & 0x1f) << 6) | (uint32(data[1]) >> 2)
|
product_id := ((uint32(data[0]) & 0x1f) << 6) | (uint32(data[1]) >> 2)
|
||||||
fmt.Printf("%d %d\n", data[0], data[1])
|
fmt.Printf("%d %d\n", data[0], data[1])
|
||||||
if product_id != 413 { // FIXME.
|
if product_id != 413 { // FIXME.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -91,9 +89,9 @@ fmt.Printf("%d %d\n", data[0], data[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
fisb_hours := (uint32(data[2]) & 0x7c) >> 2
|
fisb_hours := (uint32(data[2]) & 0x7c) >> 2
|
||||||
fisb_minutes := ((uint32(data[2]) & 0x03) << 4) | (uint32(data[3]) >> 4)
|
fisb_minutes := ((uint32(data[2]) & 0x03) << 4) | (uint32(data[3]) >> 4)
|
||||||
fisb_length := frame_len - 4
|
fisb_length := frame_len - 4
|
||||||
fisb_data := data[4:]
|
fisb_data := data[4:]
|
||||||
|
|
||||||
p := dlac_decode(fisb_data, fisb_length)
|
p := dlac_decode(fisb_data, fisb_length)
|
||||||
fmt.Printf("%v\n", p)
|
fmt.Printf("%v\n", p)
|
||||||
|
@ -103,9 +101,9 @@ fmt.Printf("%d %d\n", data[0], data[1])
|
||||||
|
|
||||||
func decodeUplink(frame []byte) {
|
func decodeUplink(frame []byte) {
|
||||||
position_valid := (uint32(frame[5]) & 0x01) != 0
|
position_valid := (uint32(frame[5]) & 0x01) != 0
|
||||||
raw_lat := (uint32(frame[0]) << 15) | (uint32(frame[1]) << 7) | (uint32(frame[2]) >> 1)
|
raw_lat := (uint32(frame[0]) << 15) | (uint32(frame[1]) << 7) | (uint32(frame[2]) >> 1)
|
||||||
|
|
||||||
raw_lon := ((uint32(frame[2]) & 0x01) << 23) | (uint32(frame[3]) << 15) | (uint32(frame[4]) << 7) | (uint32(frame[5]) >> 1)
|
raw_lon := ((uint32(frame[2]) & 0x01) << 23) | (uint32(frame[3]) << 15) | (uint32(frame[4]) << 7) | (uint32(frame[5]) >> 1)
|
||||||
lat := float64(raw_lat) * 360.0 / 16777216.0
|
lat := float64(raw_lat) * 360.0 / 16777216.0
|
||||||
lon := float64(raw_lon) * 360.0 / 16777216.0
|
lon := float64(raw_lon) * 360.0 / 16777216.0
|
||||||
|
|
||||||
|
@ -118,8 +116,8 @@ func decodeUplink(frame []byte) {
|
||||||
|
|
||||||
utc_coupled := (uint32(frame[6]) & 0x80) != 0
|
utc_coupled := (uint32(frame[6]) & 0x80) != 0
|
||||||
app_data_valid := (uint32(frame[6]) & 0x20) != 0
|
app_data_valid := (uint32(frame[6]) & 0x20) != 0
|
||||||
slot_id := uint32(frame[6]) & 0x1f;
|
slot_id := uint32(frame[6]) & 0x1f
|
||||||
tisb_site_id := uint32(frame[7]) >> 4;
|
tisb_site_id := uint32(frame[7]) >> 4
|
||||||
|
|
||||||
logger.Printf("position_valid=%t, %.04f, %.04f, %t, %t, %d, %d\n", position_valid, lat, lon, utc_coupled, app_data_valid, slot_id, tisb_site_id)
|
logger.Printf("position_valid=%t, %.04f, %.04f, %t, %t, %d, %d\n", position_valid, lat, lon, utc_coupled, app_data_valid, slot_id, tisb_site_id)
|
||||||
|
|
||||||
|
@ -131,11 +129,11 @@ func decodeUplink(frame []byte) {
|
||||||
num_info_frames := 0
|
num_info_frames := 0
|
||||||
pos := 0
|
pos := 0
|
||||||
total_len := len(app_data)
|
total_len := len(app_data)
|
||||||
for (num_info_frames < UPLINK_MAX_INFO_FRAMES) && (pos + 2 <= total_len) {
|
for (num_info_frames < UPLINK_MAX_INFO_FRAMES) && (pos+2 <= total_len) {
|
||||||
data := app_data[pos:]
|
data := app_data[pos:]
|
||||||
frame_length := (uint32(data[0]) << 1) | (uint32(data[1]) >> 7)
|
frame_length := (uint32(data[0]) << 1) | (uint32(data[1]) >> 7)
|
||||||
frame_type := uint32(data[1]) & 0x0f
|
frame_type := uint32(data[1]) & 0x0f
|
||||||
if pos + int(frame_length) > total_len {
|
if pos+int(frame_length) > total_len {
|
||||||
break // Overrun?
|
break // Overrun?
|
||||||
}
|
}
|
||||||
if frame_length == 0 && frame_type == 0 {
|
if frame_length == 0 && frame_type == 0 {
|
||||||
|
@ -149,7 +147,7 @@ func decodeUplink(frame []byte) {
|
||||||
|
|
||||||
func parseInput(buf string) {
|
func parseInput(buf string) {
|
||||||
buf = strings.Trim(buf, "\r\n") // Remove newlines.
|
buf = strings.Trim(buf, "\r\n") // Remove newlines.
|
||||||
x := strings.Split(buf, ";") // We want to discard everything before the first ';'.
|
x := strings.Split(buf, ";") // We want to discard everything before the first ';'.
|
||||||
if len(x) == 0 {
|
if len(x) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -164,7 +162,7 @@ func parseInput(buf string) {
|
||||||
|
|
||||||
s = s[1:]
|
s = s[1:]
|
||||||
|
|
||||||
if len(s) % 2 != 0 { // Bad format.
|
if len(s)%2 != 0 { // Bad format.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,7 +180,6 @@ func parseInput(buf string) {
|
||||||
decodeUplink(frame)
|
decodeUplink(frame)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
logger = log.New(&buf, "logger: ", log.Lshortfile)
|
logger = log.New(&buf, "logger: ", log.Lshortfile)
|
||||||
reader := bufio.NewReader(os.Stdin)
|
reader := bufio.NewReader(os.Stdin)
|
||||||
|
|
56
gen_gdl90.go
56
gen_gdl90.go
|
@ -1,38 +1,36 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"bufio"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"time"
|
"fmt"
|
||||||
"strings"
|
"net"
|
||||||
"fmt"
|
"os"
|
||||||
"bufio"
|
"strings"
|
||||||
"os"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// http://www.faa.gov/nextgen/programs/adsb/wsa/media/GDL90_Public_ICD_RevA.PDF
|
// http://www.faa.gov/nextgen/programs/adsb/wsa/media/GDL90_Public_ICD_RevA.PDF
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ipadAddr = "192.168.10.255:4000" // Port 4000 for FreeFlight RANGR.
|
ipadAddr = "192.168.10.255:4000" // Port 4000 for FreeFlight RANGR.
|
||||||
maxDatagramSize = 8192
|
maxDatagramSize = 8192
|
||||||
UPLINK_BLOCK_DATA_BITS = 576
|
UPLINK_BLOCK_DATA_BITS = 576
|
||||||
UPLINK_BLOCK_BITS = (UPLINK_BLOCK_DATA_BITS+160)
|
UPLINK_BLOCK_BITS = (UPLINK_BLOCK_DATA_BITS + 160)
|
||||||
UPLINK_BLOCK_DATA_BYTES = (UPLINK_BLOCK_DATA_BITS/8)
|
UPLINK_BLOCK_DATA_BYTES = (UPLINK_BLOCK_DATA_BITS / 8)
|
||||||
UPLINK_BLOCK_BYTES = (UPLINK_BLOCK_BITS/8)
|
UPLINK_BLOCK_BYTES = (UPLINK_BLOCK_BITS / 8)
|
||||||
|
|
||||||
UPLINK_FRAME_BLOCKS = 6
|
UPLINK_FRAME_BLOCKS = 6
|
||||||
UPLINK_FRAME_DATA_BITS = (UPLINK_FRAME_BLOCKS * UPLINK_BLOCK_DATA_BITS)
|
UPLINK_FRAME_DATA_BITS = (UPLINK_FRAME_BLOCKS * UPLINK_BLOCK_DATA_BITS)
|
||||||
UPLINK_FRAME_BITS = (UPLINK_FRAME_BLOCKS * UPLINK_BLOCK_BITS)
|
UPLINK_FRAME_BITS = (UPLINK_FRAME_BLOCKS * UPLINK_BLOCK_BITS)
|
||||||
UPLINK_FRAME_DATA_BYTES = (UPLINK_FRAME_DATA_BITS/8)
|
UPLINK_FRAME_DATA_BYTES = (UPLINK_FRAME_DATA_BITS / 8)
|
||||||
UPLINK_FRAME_BYTES = (UPLINK_FRAME_BITS/8)
|
UPLINK_FRAME_BYTES = (UPLINK_FRAME_BITS / 8)
|
||||||
|
|
||||||
// assume 6 byte frames: 2 header bytes, 4 byte payload
|
// assume 6 byte frames: 2 header bytes, 4 byte payload
|
||||||
// (TIS-B heartbeat with one address, or empty FIS-B APDU)
|
// (TIS-B heartbeat with one address, or empty FIS-B APDU)
|
||||||
UPLINK_MAX_INFO_FRAMES = (424/6)
|
UPLINK_MAX_INFO_FRAMES = (424 / 6)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
var Crc16Table [256]uint16
|
var Crc16Table [256]uint16
|
||||||
var outConn *net.UDPConn
|
var outConn *net.UDPConn
|
||||||
|
|
||||||
|
@ -58,7 +56,7 @@ func crcInit() {
|
||||||
func crcCompute(data []byte) uint16 {
|
func crcCompute(data []byte) uint16 {
|
||||||
ret := uint16(0)
|
ret := uint16(0)
|
||||||
for i := 0; i < len(data); i++ {
|
for i := 0; i < len(data); i++ {
|
||||||
ret = Crc16Table[ret >> 8] ^ (ret << 8) ^ uint16(data[i])
|
ret = Crc16Table[ret>>8] ^ (ret << 8) ^ uint16(data[i])
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
@ -79,8 +77,8 @@ func prepareMessage(data []byte) []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the two CRC16 bytes.
|
// Add the two CRC16 bytes.
|
||||||
tmp = append(tmp, byte(crc & 0xFF))
|
tmp = append(tmp, byte(crc&0xFF))
|
||||||
tmp = append(tmp, byte(crc >> 8))
|
tmp = append(tmp, byte(crc>>8))
|
||||||
|
|
||||||
tmp = append(tmp, 0x7E) // Flag end.
|
tmp = append(tmp, 0x7E) // Flag end.
|
||||||
|
|
||||||
|
@ -109,7 +107,7 @@ func makeHeartbeat() []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
func relayUplinkMessage(msg []byte) {
|
func relayUplinkMessage(msg []byte) {
|
||||||
ret := make([]byte, len(msg) + 4)
|
ret := make([]byte, len(msg)+4)
|
||||||
// See p.15.
|
// See p.15.
|
||||||
ret[0] = 0x07 // Uplink message ID.
|
ret[0] = 0x07 // Uplink message ID.
|
||||||
ret[1] = 0x00 //TODO: Time.
|
ret[1] = 0x00 //TODO: Time.
|
||||||
|
@ -130,10 +128,9 @@ func heartBeatSender() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func parseInput(buf string) []byte {
|
func parseInput(buf string) []byte {
|
||||||
buf = strings.Trim(buf, "\r\n") // Remove newlines.
|
buf = strings.Trim(buf, "\r\n") // Remove newlines.
|
||||||
x := strings.Split(buf, ";") // We want to discard everything before the first ';'.
|
x := strings.Split(buf, ";") // We want to discard everything before the first ';'.
|
||||||
if len(x) == 0 {
|
if len(x) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -147,13 +144,13 @@ func parseInput(buf string) []byte {
|
||||||
|
|
||||||
s = s[1:]
|
s = s[1:]
|
||||||
|
|
||||||
if len(s) % 2 != 0 { // Bad format.
|
if len(s)%2 != 0 { // Bad format.
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(s)/2 != UPLINK_FRAME_DATA_BYTES {
|
if len(s)/2 != UPLINK_FRAME_DATA_BYTES {
|
||||||
fmt.Printf("UPLINK_FRAME_DATA_BYTES=%d, len(s)=%d\n", UPLINK_FRAME_DATA_BYTES, len(s))
|
fmt.Printf("UPLINK_FRAME_DATA_BYTES=%d, len(s)=%d\n", UPLINK_FRAME_DATA_BYTES, len(s))
|
||||||
// panic("Error")
|
// panic("Error")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,7 +161,6 @@ func parseInput(buf string) []byte {
|
||||||
return frame
|
return frame
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
crcInit() // Initialize CRC16 table.
|
crcInit() // Initialize CRC16 table.
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue