You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

152 lines
4.2 KiB
Go

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, nil
}
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
}