diff --git a/config/config.go b/config/config.go index 414e099..a6aee73 100644 --- a/config/config.go +++ b/config/config.go @@ -18,8 +18,8 @@ const ( // Universe represents a DMX universe with its protocol type Universe struct { - Protocol Protocol - Number uint16 + Protocol Protocol `json:"protocol"` + Number uint16 `json:"number"` } func NewUniverse(proto Protocol, num any) (Universe, error) { @@ -104,27 +104,27 @@ func makeUniverse(proto Protocol, n uint16) (Universe, error) { // Config represents the application configuration type Config struct { - Targets []Target `toml:"target"` - Mappings []Mapping `toml:"mapping"` + Targets []Target `toml:"target" json:"targets"` + Mappings []Mapping `toml:"mapping" json:"mappings"` } // Target represents a target address for an output universe type Target struct { - Universe Universe `toml:"universe"` - Address string `toml:"address"` + Universe Universe `toml:"universe" json:"universe"` + Address string `toml:"address" json:"address"` } // Mapping represents a single channel mapping rule type Mapping struct { - From FromAddr `toml:"from"` - To ToAddr `toml:"to"` + From FromAddr `toml:"from" json:"from"` + To ToAddr `toml:"to" json:"to"` } // FromAddr represents a source universe address with channel range type FromAddr struct { - Universe Universe - ChannelStart int // 1-indexed - ChannelEnd int // 1-indexed + Universe Universe `json:"universe"` + ChannelStart int `json:"channel_start"` // 1-indexed + ChannelEnd int `json:"channel_end"` // 1-indexed } func (a *FromAddr) UnmarshalTOML(data any) error { @@ -210,8 +210,8 @@ func (a *FromAddr) Count() int { // ToAddr represents a destination universe address with starting channel type ToAddr struct { - Universe Universe - ChannelStart int // 1-indexed + Universe Universe `json:"universe"` + ChannelStart int `json:"channel_start"` // 1-indexed } func (a *ToAddr) UnmarshalTOML(data any) error { diff --git a/main.go b/main.go index de5a606..1ec90ad 100644 --- a/main.go +++ b/main.go @@ -1,10 +1,12 @@ package main import ( + "encoding/json" "flag" "fmt" "log" "net" + "net/http" "os" "os/signal" "strconv" @@ -35,6 +37,7 @@ func main() { artnetListen := flag.String("artnet-listen", ":6454", "artnet listen address (empty to disable)") artnetBroadcast := flag.String("artnet-broadcast", "auto", "artnet broadcast addresses (comma-separated, or 'auto')") sacnInterface := flag.String("sacn-interface", "", "network interface for sACN multicast") + apiListen := flag.String("api-listen", ":8080", "HTTP API listen address (empty to disable)") debug := flag.Bool("debug", false, "log incoming/outgoing dmx packets") flag.Parse() @@ -190,6 +193,22 @@ func main() { discovery.Start() } + // Start HTTP API server + if *apiListen != "" { + go func() { + mux := http.NewServeMux() + mux.HandleFunc("/api/config", app.handleConfig) + server := &http.Server{ + Addr: *apiListen, + Handler: mux, + } + log.Printf("[api] listening addr=%s", *apiListen) + if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { + log.Printf("[api] server error: %v", err) + } + }() + } + // Wait for interrupt sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) @@ -288,6 +307,12 @@ func (a *App) sendOutputs(outputs []remap.Output) { } } +func (a *App) handleConfig(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.Header().Set("Server", "artmap") + json.NewEncoder(w).Encode(a.cfg) +} + func init() { log.SetFlags(log.Ltime | log.Lmicroseconds) }