package tui import ( "sync" "fmt" "log" "time" "math" "context" "google.golang.org/grpc" "google.golang.org/grpc/status" "google.golang.org/grpc/credentials/insecure" pb "FRMS/internal/pkg/grpc" ) // this package will interact with the server to get system status type TUIClient struct { Ip string Port int client pb.ManagementClient Active } type Active struct { sync.Mutex bool int } func NewTUIClient(ip string, port int) *TUIClient { t := &TUIClient{Ip:ip,Port:port} return t } func (t *TUIClient) Start() error { t.Connect() return nil } func (t *TUIClient) Timeout() int { t.Active.Lock() defer t.Active.Unlock() if t.Active.int < 9 { v := int( 5 * math.Pow(float64(2), float64(t.Active.int))) t.Active.int += 1 return v } else { return 0 } } func (t *TUIClient) Connect() { // connect to server and register as client var conn *grpc.ClientConn var err error var opts []grpc.DialOption opts = append(opts,grpc.WithTransportCredentials(insecure.NewCredentials())) for { conn, err = grpc.Dial(fmt.Sprintf("%v:%v",t.Ip,t.Port),opts...) code := status.Code(err) if code != 0 { if code == (5 | 14) { to := t.Timeout() if to == 0 { log.Fatal("Failed to connect to central server") } fmt.Printf("Server currently down, reconnecting in %v ms\n",to) time.Sleep(time.Duration(to) * time.Millisecond) } else { log.Fatal("Central server currently unavailable") } } //t.client = pb.NewManagementClient(conn) break; } // handle handshake logic here client := pb.NewHandshakeClient(conn) req := &pb.TUIClientRequest{ClientId:10120} resp, err := client.TUIClientDiscoveryHandler(context.Background(),req) if err != nil { log.Fatal(err) } // setting up server connection with provided port t.Ip = resp.GetServerIp() t.Port = int(resp.GetServerPort()) for { conn, err = grpc.Dial(fmt.Sprintf("%v:%v",t.Ip,t.Port),opts...) code := status.Code(err) if code != 0 { if code == (5 | 14) { to := t.Timeout() if to == 0 { log.Fatal("Failed to connect to central server") } fmt.Printf("Server currently down, reconnecting in %v ms\n",to) time.Sleep(time.Duration(to) * time.Millisecond) } else { log.Fatal("Central server currently unavailable") } } t.client = pb.NewManagementClient(conn) break; } } func (t *TUIClient) GetReactors() (map[uint32]*Reactor, error) { req := &pb.GetReactorsRequest{} r := make(map[uint32]*Reactor) resp, err := t.client.GetReactors(context.Background(), req) if err != nil { return r, err } for _, v := range resp.GetReactors() { m := make(map[int]*Device) r[v.GetId()] = &Reactor{Status:v.GetStatus(),Devices:m} } return r, nil } func (t *TUIClient) GetReactorDevices(id uint32) (map[int]*Device, error) { req := &pb.GetReactorDevicesRequest{} r := make(map[int]*Device) resp, err := t.client.GetReactorDevices(context.Background(), req) if err != nil { return r, nil } for _, v := range resp.GetDevices() { r[int(v.GetAddr())] = &Device{Type:v.GetType(),Status:v.GetStatus()} } return r, err } func (t *TUIClient) DeleteReactor(id uint32) error { req := &pb.DeleteReactorRequest{} _, err := t.client.DeleteReactor(context.Background(), req) return err } func (t *TUIClient) DeleteReactorDevice(id uint32, addr int) error { req := &pb.DeleteReactorDeviceRequest{} _, err := t.client.DeleteReactorDevice(context.Background(), req) return err }