<commit_before>package hamaprs

// #cgo LDFLAGS: -lfap
/*
#include <fap.h>
#include <stdlib.h>

// type is a reserved keyword in Go, we need something to reach p->type
fap_packet_type_t getPacketType(fap_packet_t* p) {
	if (!p) return -1;
    if (p->type != NULL) return *p->type;
    return -1;
}
*/
import "C"
import (
	"errors"
	"reflect"
	"runtime"
	"strings"
	"time"
	"unsafe"
)

type PacketType int

const (
	LocationPacketType PacketType = iota
	ObjectPacketType
	ItemPacketType
	MicePacketType
	NMEAPacketType
	WXPacketType
	MessagePacketType
	CapabilitiesPacketType
	StatusPacketType
	TelemetryPacketType
	TelemetryMessagePacketType
	DXSpotPacketType
	ExperimentalPacketType
	InvalidPacketType
)

// InvalidCoordinate is a marker for an unset position
const InvalidCoordinate float64 = 360

// Packet describes an APRS packet
type Packet struct {
	PacketType
	Timestamp           int
	SourceCallsign      string
	DestinationCallsign string
	Path                []string
	Status              string
	Symbol              string
	Latitude            float64
	Longitude           float64
	Altitude            float64
	Speed               float64
	Course              uint8
	Weather             *WeatherReport
	Telemetry           *Telemetry
	RawMessage          string
	MicE                string
	Message             string
	Comment             string
}

// WeatherReport describes the weather related part of an APRS packet
type WeatherReport struct {
	Temperature       float64
	InsideTemperature float64
	Humidity          uint8
	InsideHumidity    uint8
	WindGust          float64
	WindDirection     uint8
	WindSpeed         float64
	Pressure          float64
}

// Telemetry describes the telemetry related part of an APRS packet
type Telemetry struct {
	Val1, Val2, Val3, Val4, Val5 float64
}

// Parser is an APRS Parser
type Parser struct{}

// Returns a new APRS Parser
func NewParser() *Parser {
	C.fap_init()
	p := &Parser{}
	runtime.SetFinalizer(p, func() {
		C.fap_cleanup()
	})
	return p
}

// ParsePacket parse raw packet string and return a new Packet
func (p *Parser) ParsePacket(raw string, isAX25 bool) (*Packet, error) {
	packet := &Packet{Latitude: InvalidCoordinate, Longitude: InvalidCoordinate}
	return p.FillAprsPacket(raw, isAX25, packet)
}

func (p *Parser) FillAprsPacket(raw string, isAX25 bool, packet *Packet) (*Packet, error) {
	message_cstring := C.CString(raw)
	message_length := C.uint(len(raw))
	defer C.free(unsafe.Pointer(message_cstring))

	cpacket := C.fap_parseaprs(message_cstring, message_length, C.short(boolToInt(isAX25)))

	defer C.fap_free(cpacket)

	if cpacket.error_code != nil {
		return nil, errors.New("Unable to parse APRS message")
	}

	packet.Timestamp = int(time.Now().Unix())
	packet.SourceCallsign = strings.ToUpper(C.GoString(cpacket.src_callsign))
	packet.DestinationCallsign = strings.ToUpper(C.GoString(cpacket.dst_callsign))
	packet.Latitude = parseNilableCoordinate(cpacket.latitude)<commit_msg>rename FillAprsPacket to FillPacket<commit_after>package hamaprs

// #cgo LDFLAGS: -lfap
/*
#include <fap.h>
#include <stdlib.h>

// type is a reserved keyword in Go, we need something to reach p->type
fap_packet_type_t getPacketType(fap_packet_t* p) {
	if (!p) return -1;
    if (p->type != NULL) return *p->type;
    return -1;
}
*/
import "C"
import (
	"errors"
	"reflect"
	"runtime"
	"strings"
	"time"
	"unsafe"
)

type PacketType int

const (
	LocationPacketType PacketType = iota
	ObjectPacketType
	ItemPacketType
	MicePacketType
	NMEAPacketType
	WXPacketType
	MessagePacketType
	CapabilitiesPacketType
	StatusPacketType
	TelemetryPacketType
	TelemetryMessagePacketType
	DXSpotPacketType
	ExperimentalPacketType
	InvalidPacketType
)

// InvalidCoordinate is a marker for an unset position
const InvalidCoordinate float64 = 360

// Packet describes an APRS packet
type Packet struct {
	PacketType
	Timestamp           int
	SourceCallsign      string
	DestinationCallsign string
	Path                []string
	Status              string
	Symbol              string
	Latitude            float64
	Longitude           float64
	Altitude            float64
	Speed               float64
	Course              uint8
	Weather             *WeatherReport
	Telemetry           *Telemetry
	RawMessage          string
	MicE                string
	Message             string
	Comment             string
}

// WeatherReport describes the weather related part of an APRS packet
type WeatherReport struct {
	Temperature       float64
	InsideTemperature float64
	Humidity          uint8
	InsideHumidity    uint8
	WindGust          float64
	WindDirection     uint8
	WindSpeed         float64
	Pressure          float64
}

// Telemetry describes the telemetry related part of an APRS packet
type Telemetry struct {
	Val1, Val2, Val3, Val4, Val5 float64
}

// Parser is an APRS Parser
type Parser struct{}

// Returns a new APRS Parser
func NewParser() *Parser {
	C.fap_init()
	p := &Parser{}
	runtime.SetFinalizer(p, func() {
		C.fap_cleanup()
	})
	return p
}

// ParsePacket parse raw packet string and return a new Packet
func (p *Parser) ParsePacket(raw string, isAX25 bool) (*Packet, error) {
	packet := &Packet{Latitude: InvalidCoordinate, Longitude: InvalidCoordinate}
	return p.FillPacket(raw, isAX25, packet)
}

func (p *Parser) FillPacket(raw string, isAX25 bool, packet *Packet) (*Packet, error) {
	message_cstring := C.CString(raw)
	message_length := C.uint(len(raw))
	defer C.free(unsafe.Pointer(message_cstring))

	cpacket := C.fap_parseaprs(message_cstring, message_length, C.short(boolToInt(isAX25)))

	defer C.fap_free(cpacket)

	if cpacket.error_code != nil {
		return nil, errors.New("Unable to parse APRS message")
	}

	packet.Timestamp = int(time.Now().Unix())
	packet.SourceCallsign = strings.ToUpper(C.GoString(cpacket.src_callsign))
	packet.DestinationCallsign = strings.ToUpper(C.GoString(cpacket.dst_callsign))
	packet.Latitude = parseNilableCoordinate(cpacket.latitude)
{'fraction_non_alphanumeric': 0.07943453382699428, 'fraction_numerical': 0.014809828340626052, 'mean_word_length': 3.3190406976744184, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2161398', 'n_tokens_mistral': 1972, 'n_tokens_neox': 1867, 'n_words': 524}