Initial implementation of SkyView - ADS-B aircraft tracker
- Go application with embedded static files for dump1090 frontend - TCP client for SBS-1/BaseStation format (port 30003) - Real-time WebSocket updates with aircraft tracking - Modern web frontend with Leaflet maps and mobile-responsive design - Aircraft table with filtering/sorting and statistics dashboard - Origin configuration for receiver location and distance calculations - Automatic config.json loading from current directory - Foreground execution by default with optional -daemon flag 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
commit
8ce4f4c397
19 changed files with 1971 additions and 0 deletions
118
internal/config/config.go
Normal file
118
internal/config/config.go
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Server ServerConfig `json:"server"`
|
||||
Dump1090 Dump1090Config `json:"dump1090"`
|
||||
Origin OriginConfig `json:"origin"`
|
||||
}
|
||||
|
||||
type ServerConfig struct {
|
||||
Address string `json:"address"`
|
||||
Port int `json:"port"`
|
||||
}
|
||||
|
||||
type Dump1090Config struct {
|
||||
Host string `json:"host"`
|
||||
DataPort int `json:"data_port"`
|
||||
}
|
||||
|
||||
type OriginConfig struct {
|
||||
Latitude float64 `json:"latitude"`
|
||||
Longitude float64 `json:"longitude"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
func Load() (*Config, error) {
|
||||
cfg := &Config{
|
||||
Server: ServerConfig{
|
||||
Address: ":8080",
|
||||
Port: 8080,
|
||||
},
|
||||
Dump1090: Dump1090Config{
|
||||
Host: "localhost",
|
||||
DataPort: 30003,
|
||||
},
|
||||
Origin: OriginConfig{
|
||||
Latitude: 37.7749,
|
||||
Longitude: -122.4194,
|
||||
Name: "Default Location",
|
||||
},
|
||||
}
|
||||
|
||||
configFile := os.Getenv("SKYVIEW_CONFIG")
|
||||
if configFile == "" {
|
||||
// Check for config files in common locations
|
||||
candidates := []string{"config.json", "./config.json", "skyview.json"}
|
||||
for _, candidate := range candidates {
|
||||
if _, err := os.Stat(candidate); err == nil {
|
||||
configFile = candidate
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if configFile != "" {
|
||||
if err := loadFromFile(cfg, configFile); err != nil {
|
||||
return nil, fmt.Errorf("failed to load config file %s: %w", configFile, err)
|
||||
}
|
||||
}
|
||||
|
||||
loadFromEnv(cfg)
|
||||
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func loadFromFile(cfg *Config, filename string) error {
|
||||
data, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return json.Unmarshal(data, cfg)
|
||||
}
|
||||
|
||||
func loadFromEnv(cfg *Config) {
|
||||
if addr := os.Getenv("SKYVIEW_ADDRESS"); addr != "" {
|
||||
cfg.Server.Address = addr
|
||||
}
|
||||
|
||||
if portStr := os.Getenv("SKYVIEW_PORT"); portStr != "" {
|
||||
if port, err := strconv.Atoi(portStr); err == nil {
|
||||
cfg.Server.Port = port
|
||||
cfg.Server.Address = fmt.Sprintf(":%d", port)
|
||||
}
|
||||
}
|
||||
|
||||
if host := os.Getenv("DUMP1090_HOST"); host != "" {
|
||||
cfg.Dump1090.Host = host
|
||||
}
|
||||
|
||||
if dataPortStr := os.Getenv("DUMP1090_DATA_PORT"); dataPortStr != "" {
|
||||
if port, err := strconv.Atoi(dataPortStr); err == nil {
|
||||
cfg.Dump1090.DataPort = port
|
||||
}
|
||||
}
|
||||
|
||||
if latStr := os.Getenv("ORIGIN_LATITUDE"); latStr != "" {
|
||||
if lat, err := strconv.ParseFloat(latStr, 64); err == nil {
|
||||
cfg.Origin.Latitude = lat
|
||||
}
|
||||
}
|
||||
|
||||
if lonStr := os.Getenv("ORIGIN_LONGITUDE"); lonStr != "" {
|
||||
if lon, err := strconv.ParseFloat(lonStr, 64); err == nil {
|
||||
cfg.Origin.Longitude = lon
|
||||
}
|
||||
}
|
||||
|
||||
if name := os.Getenv("ORIGIN_NAME"); name != "" {
|
||||
cfg.Origin.Name = name
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue