safesight/agent/cmd/rk3588-agent/main.go

166 lines
3.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"context"
"flag"
"fmt"
"net"
"net/http"
"net/url"
"os"
"os/signal"
"path/filepath"
"strconv"
"strings"
"sync"
"syscall"
"time"
"rk3588sys/agent/internal/config"
"rk3588sys/agent/internal/discovery"
"rk3588sys/agent/internal/httpapi"
"rk3588sys/agent/internal/log"
"rk3588sys/agent/internal/mediaserver"
"rk3588sys/agent/internal/modelstore"
"rk3588sys/agent/internal/sysinfo"
)
var Version = "0.0.0-dev"
var GitSHA = ""
func main() {
cfgPath := flag.String("config", "", "config file path")
flag.Parse()
if strings.TrimSpace(*cfgPath) == "" {
log.Error("missing --config")
os.Exit(2)
}
cfg, err := config.Load(*cfgPath)
if err != nil {
log.Error("load config failed: " + err.Error())
os.Exit(2)
}
agentPort, err := portFromListen(cfg.Agent.Listen)
if err != nil {
log.Error("invalid agent.listen: " + err.Error())
os.Exit(2)
}
mediaPort, err := portFromBaseURL(cfg.Agent.MediaServerBaseURL)
if err != nil {
log.Error("invalid agent.media_server_base_url: " + err.Error())
os.Exit(2)
}
deviceID, err := sysinfo.DeviceID(cfg.Agent.DeviceIDPath)
if err != nil {
log.Error("device_id failed: " + err.Error())
os.Exit(2)
}
ms, err := mediaserver.New(cfg.Agent.MediaServerBaseURL, cfg.Agent.MediaServerTimeout, cfg.Agent.MediaServerRetry.MaxAttempts, cfg.Agent.MediaServerRetry.BackoffMS)
if err != nil {
log.Error("media-server client init failed: " + err.Error())
os.Exit(2)
}
store := modelstore.New(cfg.Agent.ModelsDir, cfg.Agent.MaxUploadMB)
baseDir := filepath.Dir(*cfgPath)
if abs, err := filepath.Abs(*cfgPath); err == nil {
baseDir = filepath.Dir(abs)
}
h := httpapi.New(cfg.Agent, baseDir, ms, store, deviceID, agentPort, mediaPort, Version, GitSHA)
httpSrv := &http.Server{
Addr: cfg.Agent.Listen,
Handler: h,
ReadHeaderTimeout: 5 * time.Second,
}
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
log.Info("http listening on " + cfg.Agent.Listen)
if err := httpSrv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Error("http server error: " + err.Error())
stop()
}
}()
// 自动启动 media-server如果启用
if cfg.Agent.MediaServerProcess.Enable {
time.Sleep(500 * time.Millisecond) // 等待 HTTP 服务启动
log.Info("auto-starting media-server...")
if err := h.StartMediaServer(""); err != nil {
log.Error("auto-start media-server failed: " + err.Error())
} else {
log.Info("media-server auto-started")
}
}
if cfg.Agent.DiscoveryEnable {
wg.Add(1)
go func() {
defer wg.Done()
resp := &discovery.Responder{
Port: cfg.Agent.DiscoveryPort,
DeviceID: deviceID,
DeviceName: cfg.Agent.DeviceName,
Hostname: sysinfo.Hostname(),
AgentPort: agentPort,
MediaPort: mediaPort,
Version: Version,
GitSHA: GitSHA,
}
log.Info("udp discovery listening on :" + strconv.Itoa(cfg.Agent.DiscoveryPort))
if err := resp.Run(ctx); err != nil {
log.Error("udp discovery error: " + err.Error())
stop()
}
}()
}
<-ctx.Done()
shutdownCtx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
_ = httpSrv.Shutdown(shutdownCtx)
cancel()
wg.Wait()
}
func portFromListen(listen string) (int, error) {
_, portStr, err := net.SplitHostPort(listen)
if err != nil {
return 0, err
}
p, err := strconv.Atoi(portStr)
if err != nil || p <= 0 || p > 65535 {
return 0, fmt.Errorf("invalid port: %q", portStr)
}
return p, nil
}
func portFromBaseURL(base string) (int, error) {
u, err := url.Parse(base)
if err != nil {
return 0, err
}
if u.Port() != "" {
p, err := strconv.Atoi(u.Port())
if err != nil {
return 0, err
}
return p, nil
}
if u.Scheme == "https" {
return 443, nil
}
return 80, nil
}