mirror of
https://github.com/vale981/agent
synced 2025-03-04 09:01:42 -05:00
361 lines
9.4 KiB
Go
361 lines
9.4 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"crypto/tls"
|
|
"flag"
|
|
"fmt"
|
|
"log"
|
|
"net"
|
|
"net/http"
|
|
"os"
|
|
"os/signal"
|
|
"runtime"
|
|
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/credentials"
|
|
_ "google.golang.org/grpc/encoding/gzip"
|
|
|
|
"github.com/indihub-space/agent/apiserver"
|
|
"github.com/indihub-space/agent/config"
|
|
"github.com/indihub-space/agent/lib"
|
|
"github.com/indihub-space/agent/logutil"
|
|
"github.com/indihub-space/agent/manager"
|
|
"github.com/indihub-space/agent/proto/indihub"
|
|
"github.com/indihub-space/agent/share"
|
|
"github.com/indihub-space/agent/solo"
|
|
"github.com/indihub-space/agent/version"
|
|
)
|
|
|
|
const (
|
|
defaultAPIPort uint64 = 2020
|
|
)
|
|
|
|
var (
|
|
flagINDIServerManagerAddr string
|
|
flagPHD2ServerAddr string
|
|
flagINDIServerAddr string
|
|
flagINDIProfile string
|
|
flagToken string
|
|
flagConfFile string
|
|
flagCompress bool
|
|
flagAPITLS bool
|
|
flagAPIPort uint64
|
|
flagAPIOrigins string
|
|
flagMode string
|
|
flagLogFile string
|
|
|
|
indiServerAddr string
|
|
|
|
httpClientSM = http.Client{}
|
|
)
|
|
|
|
func init() {
|
|
// restrict number of system-threads to number of cores
|
|
runtime.GOMAXPROCS(runtime.NumCPU())
|
|
|
|
flag.StringVar(
|
|
&flagINDIServerManagerAddr,
|
|
"indi-server-manager",
|
|
"raspberrypi.local:8624",
|
|
"INDI-server Manager address (host:port)",
|
|
)
|
|
flag.StringVar(
|
|
&flagINDIServerAddr,
|
|
"indi-server",
|
|
"",
|
|
"INDI-server address (host:port) to connect without Web Manager",
|
|
)
|
|
flag.StringVar(
|
|
&flagMode,
|
|
"mode",
|
|
lib.ModeSolo,
|
|
`indihub-agent mode (deafult value is "solo"), there four modes:\n
|
|
solo - equipment sharing is not possible, you are connected to INDIHUB and contributing images
|
|
share - you are sharing equipment with another INDIHUB user (agent will output connection info)
|
|
robotic - equipment sharing is not possible, your equipment is controlled by INDIHUB AI (you can still watch what it is doing!)
|
|
`,
|
|
)
|
|
flag.BoolVar(
|
|
&flagCompress,
|
|
"compress",
|
|
true,
|
|
"Enable gzip-compression",
|
|
)
|
|
flag.StringVar(
|
|
&flagPHD2ServerAddr,
|
|
"phd2-server",
|
|
"",
|
|
"PHD2-server address (host:port)",
|
|
)
|
|
flag.StringVar(
|
|
&flagToken,
|
|
"token",
|
|
"",
|
|
"token - can be requested at https://indihub.space/token",
|
|
)
|
|
flag.StringVar(
|
|
&flagConfFile,
|
|
"conf",
|
|
"indihub.json",
|
|
"INDIHub Agent config file path",
|
|
)
|
|
flag.StringVar(
|
|
&flagINDIProfile,
|
|
"indi-profile",
|
|
"",
|
|
"Name of INDI-profile to share via indihub",
|
|
)
|
|
flag.BoolVar(
|
|
&flagAPITLS,
|
|
"api-tls",
|
|
false,
|
|
"serve API-server over TLS with self-signed certificate",
|
|
)
|
|
flag.Uint64Var(
|
|
&flagAPIPort,
|
|
"api-port",
|
|
defaultAPIPort,
|
|
"port to start API-server on",
|
|
)
|
|
flag.StringVar(
|
|
&flagAPIOrigins,
|
|
"api-origins",
|
|
"",
|
|
"comma-separated list of origins allowed to connect to API-server",
|
|
)
|
|
flag.StringVar(
|
|
&flagLogFile,
|
|
"log-file",
|
|
"",
|
|
"path to log file (STDOUT by default)",
|
|
)
|
|
}
|
|
|
|
func main() {
|
|
flag.Parse()
|
|
|
|
if flagLogFile != "" {
|
|
// redirect log output to file
|
|
logFile, err := os.OpenFile(flagLogFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
|
|
if err != nil {
|
|
log.Fatalf("error opening log file '%s': %s\n", flagLogFile, err)
|
|
}
|
|
defer logFile.Close()
|
|
log.SetOutput(logFile)
|
|
}
|
|
|
|
if flagMode != lib.ModeSolo && flagMode != lib.ModeShare && flagMode != lib.ModeRobotic {
|
|
log.Fatalf("Unknown mode '%s' provided\n", flagMode)
|
|
}
|
|
|
|
indiHubAddr := "relay.indihub.io:7668" // tls one
|
|
if logutil.IsDev {
|
|
indiHubAddr = "localhost:7667" // TODO: change this to optional DEV server
|
|
}
|
|
|
|
indiServerAddr := ""
|
|
indiDrivers := []*lib.INDIDriver{}
|
|
indiProfile := &lib.INDIProfile{}
|
|
if flagINDIServerAddr != "" {
|
|
// connect to INDI-server directly without Web Manager
|
|
if _, _, err := net.SplitHostPort(flagINDIServerAddr); err != nil {
|
|
log.Fatal("Bad syntax for 'indi-server' parameter, the 'host:port' format is expected")
|
|
}
|
|
log.Println("Will try to connect directly to INDI-server (Web Manager is not used)")
|
|
indiProfile.Name = flagINDIServerAddr // to let backend know that no Web Manager was used
|
|
indiServerAddr = flagINDIServerAddr
|
|
} else {
|
|
// connect to INDI-server using info from Web Manager
|
|
indiHost, _, err := net.SplitHostPort(flagINDIServerManagerAddr)
|
|
if err != nil {
|
|
log.Fatal("Bad syntax for 'indi-server-manager' parameter, the 'host:port' format is expected")
|
|
}
|
|
if flagINDIProfile == "" {
|
|
log.Fatal("'indi-profile' parameter is required")
|
|
}
|
|
|
|
// connect to INDI-server Manager
|
|
log.Printf("Connection to local INDI-Server Manager on %s...\n", flagINDIServerManagerAddr)
|
|
managerClient := manager.NewClient(flagINDIServerManagerAddr)
|
|
running, currINDIProfile, err := managerClient.GetStatus()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
log.Println("...OK")
|
|
|
|
// start required profile if it is not active and running
|
|
if !running || currINDIProfile != flagINDIProfile {
|
|
log.Printf("Setting active INDI-profile to '%s'\n", flagINDIProfile)
|
|
if err := managerClient.StopServer(); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
if err := managerClient.StartProfile(flagINDIProfile); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
} else {
|
|
log.Printf("INDI-server is running with active INDI-profile '%s'\n", flagINDIProfile)
|
|
}
|
|
|
|
// get profile connect data
|
|
indiProfile, err = managerClient.GetProfile(flagINDIProfile)
|
|
if err != nil {
|
|
log.Fatalf("could not get INDI-profile from INDI-server manager: %s", err)
|
|
}
|
|
indiServerAddr = fmt.Sprintf("%s:%d", indiHost, indiProfile.Port)
|
|
|
|
// get profile drivers data
|
|
indiDrivers, err = managerClient.GetDrivers()
|
|
if err != nil {
|
|
log.Fatalf("could not get INDI-drivers info from INDI-server manager: %s", err)
|
|
}
|
|
log.Println("INDIDrivers:")
|
|
for _, d := range indiDrivers {
|
|
log.Printf("%+v", *d)
|
|
}
|
|
}
|
|
|
|
// read token from flag or from config file if exists
|
|
if flagToken == "" {
|
|
conf, err := config.Read(flagConfFile)
|
|
if err == nil {
|
|
flagToken = conf.Token
|
|
}
|
|
}
|
|
|
|
// test connect to local INDI-server
|
|
log.Printf("Test connection to local INDI-Server on %s...\n", indiServerAddr)
|
|
indiConn, err := net.Dial("tcp", indiServerAddr)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
indiConn.Close()
|
|
log.Println("...OK")
|
|
|
|
if flagPHD2ServerAddr != "" {
|
|
log.Printf("Test connection to local PHD2-Server on %s...\n", flagPHD2ServerAddr)
|
|
phd2Conn, err := net.Dial("tcp", flagPHD2ServerAddr)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
phd2Conn.Close()
|
|
log.Println("...OK")
|
|
}
|
|
|
|
// prepare indihub-host data
|
|
indiHubHost := &indihub.INDIHubHost{
|
|
Token: flagToken,
|
|
Profile: &indihub.INDIProfile{
|
|
Id: indiProfile.ID,
|
|
Name: indiProfile.Name,
|
|
Port: indiProfile.Port,
|
|
Autostart: indiProfile.AutoStart,
|
|
Autoconnect: indiProfile.AutoConnect,
|
|
},
|
|
Drivers: make([]*indihub.INDIDriver, len(indiDrivers)),
|
|
SoloMode: flagMode == lib.ModeSolo,
|
|
IsPHD2: flagPHD2ServerAddr != "",
|
|
IsRobotic: flagMode == lib.ModeRobotic,
|
|
IsBroadcast: false,
|
|
AgentVersion: version.AgentVersion,
|
|
Os: runtime.GOOS,
|
|
Arch: runtime.GOARCH,
|
|
}
|
|
for i, driver := range indiDrivers {
|
|
indiHubHost.Drivers[i] = &indihub.INDIDriver{
|
|
Binary: driver.Binary,
|
|
Family: driver.Family,
|
|
Label: driver.Label,
|
|
Version: driver.Version,
|
|
Role: driver.Role,
|
|
Custom: driver.Custom,
|
|
Name: driver.Name,
|
|
}
|
|
}
|
|
|
|
log.Println("Connecting to the indihub.space cloud...")
|
|
opts := []grpc.DialOption{
|
|
grpc.WithDefaultCallOptions(grpc.MaxCallSendMsgSize(lib.GRPCMaxSendMsgSize)),
|
|
grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(lib.GRPCMaxRecvMsgSize)),
|
|
}
|
|
if flagCompress {
|
|
opts = append(opts, grpc.WithDefaultCallOptions(grpc.UseCompressor("gzip")))
|
|
}
|
|
|
|
if logutil.IsDev {
|
|
opts = append(opts, grpc.WithInsecure())
|
|
} else {
|
|
tlsConfig := &tls.Config{}
|
|
opts = append(opts, grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)))
|
|
}
|
|
|
|
conn, err := grpc.Dial(
|
|
indiHubAddr,
|
|
opts...,
|
|
)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
log.Println("...OK")
|
|
// close grpc client connection at the very end
|
|
defer conn.Close()
|
|
|
|
indiHubClient := indihub.NewINDIHubClient(conn)
|
|
|
|
// register host
|
|
regInfo, err := indiHubClient.RegisterHost(context.Background(), indiHubHost)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
version.CheckAgentVersion(regInfo.AgentVersion)
|
|
|
|
log.Printf("Access token: %s\n", regInfo.Token)
|
|
log.Printf("Host session token: %s\n", regInfo.SessionIDPublic)
|
|
|
|
// create config for new host if flag wasn't provided
|
|
if flagToken == "" {
|
|
conf := &config.Config{
|
|
Token: regInfo.Token,
|
|
}
|
|
if err := config.Write(flagConfFile, conf); err != nil {
|
|
log.Printf("Could not create config file %s: %s", flagConfFile, err)
|
|
}
|
|
}
|
|
|
|
// prepare all modes
|
|
soloMode := solo.NewMode(indiHubClient, regInfo, indiServerAddr)
|
|
shareMode := share.NewMode(indiHubClient, regInfo, indiServerAddr, flagPHD2ServerAddr, lib.ModeShare)
|
|
roboticMode := share.NewMode(indiHubClient, regInfo, indiServerAddr, flagPHD2ServerAddr, lib.ModeRobotic)
|
|
|
|
// start API-server
|
|
apiServer := apiserver.NewAPIServer(
|
|
regInfo.Token,
|
|
indiServerAddr,
|
|
flagPHD2ServerAddr,
|
|
flagAPIPort,
|
|
flagAPITLS,
|
|
flagAPIOrigins,
|
|
flagMode,
|
|
flagINDIProfile,
|
|
map[string]apiserver.AgentMode{
|
|
lib.ModeSolo: soloMode,
|
|
lib.ModeShare: shareMode,
|
|
lib.ModeRobotic: roboticMode,
|
|
},
|
|
)
|
|
|
|
go func() {
|
|
sigint := make(chan os.Signal, 1)
|
|
signal.Notify(sigint, os.Interrupt)
|
|
|
|
sig := <-sigint
|
|
log.Println("Stopping API-server gracefully. OS signal received:", sig)
|
|
|
|
// close connections to local INDI-server
|
|
apiServer.Stop()
|
|
}()
|
|
|
|
// start API-server and indihub-agent in the current mode
|
|
apiServer.Start()
|
|
}
|