package tui import ( "sync" "fmt" "log" "time" "math" "context" "FRMS/internal/pkg/system" "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 { Id uint32 Ip string Port int ClientConn *grpc.ClientConn Active } type Active struct { sync.Mutex bool int } func NewTUIClient(ip string, port int, ifconfig string) *TUIClient { id, err := system.GetId(ifconfig) if err != nil { log.Fatal(err) } t := &TUIClient{Id:id,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:t.Id} resp, err := client.TUIClientDiscoveryHandler(context.Background(),req) if err != nil { log.Fatal(err) } conn.Close() // closing old connection // 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.ClientConn = conn break; } } // going to redo this idk wtf i was thinking // we just want a way to do two things // a) get all devices when we first select a reactor // b) ping the cs every 500ms-1s for updates and get back a list of devs that have changed func (t *TUIClient) GetDevices(id ...uint32) (map[uint32]*Device, error) { // returns var rid uint32 if len(id) > 0 && id[0] != 0 { rid = id[0] } req := &pb.GetDevicesRequest{ClientId:t.Id,ReactorId:rid} r := make(map[uint32]*Device) client := pb.NewManagementClient(t.ClientConn) resp, err := client.GetDevices(context.Background(), req) if err != nil { return r, err } for _, v := range resp.GetDevices() { r[v.GetId()] = &Device{Type:v.GetType(),Status:v.GetStatus(),Id:v.GetId(),Data:v.GetData(),Index:v.GetIndex()} } return r, err } func (t *TUIClient) DeleteReactor(id uint32) error { req := &pb.DeleteReactorRequest{} client := pb.NewManagementClient(t.ClientConn) _, err := client.DeleteReactor(context.Background(), req) return err } func (t *TUIClient) DeleteReactorDevice(id uint32, addr int) error { req := &pb.DeleteReactorDeviceRequest{} client := pb.NewManagementClient(t.ClientConn) _, err := client.DeleteReactorDevice(context.Background(), req) return err }