package app import ( "flag" "net" "os" "os/signal" "syscall" "git.espin.casa/albert/cml04-printer-robot/internal/logging" "git.espin.casa/albert/cml04-printer-robot/internal/server" "git.espin.casa/albert/cml04-printer-robot/internal/service" "git.espin.casa/albert/cml04-printer-robot/internal/vnode" "git.espin.casa/albert/cml04-printer-robot/pkg/api" "git.espin.casa/albert/logger" "google.golang.org/grpc" "google.golang.org/grpc/reflection" ) func Run() error { // flags apiAddr := flag.String("api", "localhost:3333", "API server address") logLevel := flag.String("level", "debug", "log level") mqttAddr := flag.String("mqtt_addr", "tcp://10.1.152.13:1883", "MQTT address") mqttTopic := flag.String("mqtt_topic", "vnode/ata12/robot", "MQTT topic") // parse flags flag.Parse() // setup logger log := logger.New(os.Stdout, *logLevel) // create log fields logFields := logger.LogFields{ "app_name": "cml04-printer-robot", "debug_legel": *logLevel, "mqtt_address": *mqttAddr, "api_bind_address": *apiAddr, } // create broker broker, err := vnode.NewBroker(*mqttAddr, log) if err != nil { log.Error("create new broker failed", err, logFields) return err } // start broker if err := broker.Connect(); err != nil { log.Error("start broker failed", err, logFields) return err } defer broker.Close() // create main service svc := service.NewService(broker) // add logging capabilities to main service svc = logging.NewLoggingService(svc, log) // create data channel dataChannel := make(chan []byte) // create error channel errorCallback := make(chan error) // create done channel done := make(chan struct{}) // subscribe robot data topic go broker.SubscribeToMQTTTopic(*mqttTopic, dataChannel, errorCallback, done) // get data from channel go func() { for { select { case data := <-dataChannel: if err := svc.RobotEventDataHandler(data); err != nil { log.Error("error robot event handler", err, logFields) } case err := <-errorCallback: log.Error("error callback", err, logFields) case <-done: log.Info("done callback", logFields) } } }() // create grpc server s := grpc.NewServer() // create api server transport server := server.NewAPIServer(svc) // register service api.RegisterRobotServiceServer(s, server) // Reflection grpc server reflection.Register(s) // create grpc server lis, err := net.Listen("tcp", *apiAddr) if err != nil { log.Error("failed to listen", err, logFields) return err } // start service server go func() { if err := s.Serve(lis); err != nil { log.Error("failed to serve gRPC", err, logFields) return } }() // start banner log.Info("cml04 printer robot service started", logFields) // wait signal to finish signal := WaitSignal() // end subscriber close(done) log.Info("signal received", logger.LogFields{ "signal": signal, }) return nil } // WaitSignal catching exit signal func WaitSignal() os.Signal { ch := make(chan os.Signal, 2) signal.Notify( ch, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM, ) for { sig := <-ch switch sig { case syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM: return sig } } }