package server import ( // "fmt" "time" "sync" // "net" // "log" "context" "FRMS/internal/pkg/logging" // "google.golang.org/grpc" pb "FRMS/internal/pkg/grpc" ) // implement tui specific manager to be called for each client conn type TUIManager struct { *Manager // embedded manager for access to methods and client StatusMon *StatusMonitor // use it for all devs coming in Err chan error *Timeout *pb.UnimplementedManagementServer } type Timeout struct { Alert chan bool LastSeen time.Time TO time.Duration sync.Mutex } func NewTUIManager(c *Client, sys *SystemViewer, err chan error) GeneralManager { m := NewManager(err) t := &TUIManager{Err: err} alert := make(chan bool) t.Timeout = &Timeout{Alert:alert,TO:time.Duration(2500*time.Millisecond)} // short time outs are fine because we will just rejoin t.Manager = m t.StatusMon = NewStatusMonitor("TUI",c.Id,sys) t.Manager.UpdateClient(c) return t } func (t *TUIManager) Start() { // t.PingReset() t.Manager.Start() logging.Debug(logging.DStart,"TMA %v starting", t.Id) go t.Timeoutd() //go t.Monitor(conn) } func (t *TUIManager) Exit() { t.Manager.Exit() logging.Debug(logging.DExit,"TMA %v exiting",t.Id) } func (t *Timeout) PingReset() { t.Lock() defer t.Unlock() t.LastSeen = time.Now() } func (t *TUIManager) Timeoutd() { for t.IsActive() { if sleep, elapsed := t.Elapsed(); elapsed { // timeout elapsed logging.Debug(logging.DClient,"TMA %V client not responding", t.Id) t.Exit() } else { time.Sleep(sleep) } } } func (t *Timeout) Elapsed() (time.Duration, bool) { t.Lock() defer t.Unlock() now := time.Now() if now.After(t.LastSeen.Add(t.TO)) { // timeout expired return 0 * time.Second, true } else { sleep := t.LastSeen.Add(t.TO).Sub(now) return sleep, false } } // tui client requests and logic will be down here func (t *TUIManager) GetDevices(ctx context.Context, req *pb.GetDevicesRequest) (*pb.GetDevicesResponse, error) { go t.PingReset() devices := []*pb.Dev{} resp := &pb.GetDevicesResponse{ClientId:t.Id,Devices:devices} if req.GetReactorId() > 0 || req.GetRefresh() { logging.Debug(logging.DClient,"TMA %v client requested devs from %v",t.Id,req.GetReactorId()) resp.ReactorId = req.GetReactorId() t.StatusMon.UpdateListener(t.Id, req.GetReactorId()) } devs := t.StatusMon.GetBuffer() // always empty buffer for _, v := range devs { resp.Devices = append(resp.Devices, &pb.Dev{Id:v.Id,Type:v.Type,Status:v.Status,Data:v.Data,Index:v.Index}) } if len(resp.Devices) > 0 { logging.Debug(logging.DClient,"TMA %v sending %v devices to client" ,t.Id, len(resp.Devices)) } return resp, nil } func (t *TUIManager) DeleteReactors(ctx context.Context, req *pb.DeleteReactorRequest) (*pb.DeleteReactorResponse, error) { go t.PingReset() // return &pb.DeleteReactorResponse{}, nil } func (t *TUIManager) DeleteReactorDevice(ctx context.Context, req *pb.DeleteReactorDeviceRequest) (*pb.DeleteReactorDeviceResponse, error) { go t.PingReset() // return &pb.DeleteReactorDeviceResponse{}, nil }