first
This commit is contained in:
@@ -0,0 +1,287 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"spektr/internal/config"
|
||||
"spektr/internal/discovery"
|
||||
grpcclient "spektr/internal/grpc"
|
||||
pb "spektr/internal/grpc/pb"
|
||||
|
||||
"github.com/wailsapp/wails/v2/pkg/runtime"
|
||||
)
|
||||
|
||||
const HardAddr = "192.168.1.10:50051"
|
||||
|
||||
type App struct {
|
||||
ctx context.Context
|
||||
mu sync.Mutex
|
||||
client *grpcclient.Client
|
||||
currentFrequency string
|
||||
connectionStatus string
|
||||
}
|
||||
|
||||
func NewApp() *App {
|
||||
return &App{
|
||||
currentFrequency: "145",
|
||||
connectionStatus: "модуль не подключен",
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) startup(ctx context.Context) {
|
||||
a.ctx = ctx
|
||||
|
||||
go func() {
|
||||
client, status := connectClient(ctx)
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
a.client = client
|
||||
a.connectionStatus = status
|
||||
}()
|
||||
}
|
||||
|
||||
func (a *App) Quit() {
|
||||
a.mu.Lock()
|
||||
client := a.client
|
||||
a.client = nil
|
||||
a.mu.Unlock()
|
||||
|
||||
if client != nil {
|
||||
_ = client.Close()
|
||||
}
|
||||
runtime.Quit(a.ctx)
|
||||
}
|
||||
|
||||
type DeviceResponse struct {
|
||||
Status string `json:"status"`
|
||||
Frequency string `json:"frequency"`
|
||||
}
|
||||
|
||||
func (a *App) CheckConnection() (DeviceResponse, error) {
|
||||
log.Println("CheckConnection called")
|
||||
start := time.Now()
|
||||
log.Println("[TIMING] CheckConnection START")
|
||||
resp := DeviceResponse{
|
||||
Status: "модуль не подключен",
|
||||
Frequency: a.getFrequency(),
|
||||
}
|
||||
|
||||
//клиента вызываю в другом месте теперь
|
||||
//client, err := a.getClientOrConnect()
|
||||
//if err != nil {
|
||||
// return resp, err
|
||||
//}
|
||||
|
||||
//avMsg, err := client.Send(&pb.ClientMessage{
|
||||
// RequestId: requestID(),
|
||||
// Payload: &pb.ClientMessage_Av{Av: &pb.AvCommand{}},
|
||||
//})
|
||||
t1 := time.Now()
|
||||
avMsg, err := a.sendWithReconnect(func() *pb.ClientMessage {
|
||||
return &pb.ClientMessage{
|
||||
RequestId: requestID(),
|
||||
Payload: &pb.ClientMessage_Av{Av: &pb.AvCommand{}},
|
||||
}
|
||||
})
|
||||
log.Printf("[TIMING] AV request took: %v", time.Since(t1))
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
if errMsg := avMsg.GetError(); errMsg != nil {
|
||||
return resp, errors.New(errMsg.GetMessage())
|
||||
}
|
||||
if av := avMsg.GetAv(); av != nil {
|
||||
resp.Status = fmt.Sprintf("HW: %s FW: %s", av.GetHw(), av.GetSw())
|
||||
}
|
||||
|
||||
//freqMsg, err := client.Send(&pb.ClientMessage{
|
||||
// RequestId: requestID(),
|
||||
// Payload: &pb.ClientMessage_GetFrequency{GetFrequency: &pb.GetFrequencyCommand{}},
|
||||
//})
|
||||
t2 := time.Now()
|
||||
freqMsg, err := a.sendWithReconnect(func() *pb.ClientMessage {
|
||||
return &pb.ClientMessage{
|
||||
RequestId: requestID(),
|
||||
Payload: &pb.ClientMessage_GetFrequency{GetFrequency: &pb.GetFrequencyCommand{}},
|
||||
}
|
||||
})
|
||||
log.Printf("[TIMING] GetFreq request took: %v", time.Since(t2))
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
if errMsg := freqMsg.GetError(); errMsg != nil {
|
||||
return resp, errors.New(errMsg.GetMessage())
|
||||
}
|
||||
if freq := freqMsg.GetGetFrequency(); freq != nil {
|
||||
resp.Frequency = strconv.FormatUint(uint64(freq.GetFrequency()), 10)
|
||||
a.setFrequency(resp.Frequency)
|
||||
}
|
||||
|
||||
a.mu.Lock()
|
||||
a.connectionStatus = resp.Status
|
||||
a.mu.Unlock()
|
||||
log.Printf("[TIMING] CheckConnection TOTAL: %v", time.Since(start))
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (a *App) SetFrequency(freq string) (string, error) {
|
||||
val, err := strconv.Atoi(freq)
|
||||
if err != nil || val < 70 || val > 8545 {
|
||||
//return "", errors.New("вводимое значение должно быть целым положительным числом")
|
||||
return "", errors.New(`
|
||||
- значение может быть только числом
|
||||
- диапазон от 70 до 8545
|
||||
`)
|
||||
}
|
||||
|
||||
//клиента я вызываю теперь в другом месте
|
||||
//client, err := a.getClientOrConnect()
|
||||
//if err != nil {
|
||||
// return "", err
|
||||
//}
|
||||
|
||||
//resp, err := client.Send(&pb.ClientMessage{
|
||||
// RequestId: requestID(),
|
||||
// Payload: &pb.ClientMessage_SetFrequency{
|
||||
// SetFrequency: &pb.SetFrequencyCommand{Frequency: uint32(val)},
|
||||
// },
|
||||
//})
|
||||
resp, err := a.sendWithReconnect(func() *pb.ClientMessage {
|
||||
return &pb.ClientMessage{
|
||||
RequestId: requestID(),
|
||||
Payload: &pb.ClientMessage_SetFrequency{
|
||||
SetFrequency: &pb.SetFrequencyCommand{Frequency: uint32(val)},
|
||||
},
|
||||
}
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if errMsg := resp.GetError(); errMsg != nil {
|
||||
return "", errors.New(errMsg.GetMessage())
|
||||
}
|
||||
if ack := resp.GetSetFrequency(); ack != nil && !ack.GetOk() {
|
||||
return "", errors.New("не удалось установить частоту")
|
||||
}
|
||||
|
||||
freqStr := strconv.Itoa(val)
|
||||
a.setFrequency(freqStr)
|
||||
return freqStr, nil
|
||||
}
|
||||
|
||||
func (a *App) getClient() *grpcclient.Client {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
return a.client
|
||||
}
|
||||
|
||||
func (a *App) getClientOrConnect() (*grpcclient.Client, error) {
|
||||
client := a.getClient()
|
||||
if client != nil {
|
||||
return client, nil
|
||||
}
|
||||
|
||||
ctx := a.ctx
|
||||
if ctx == nil {
|
||||
ctx = context.Background()
|
||||
}
|
||||
|
||||
client, status := connectClient(ctx)
|
||||
if client == nil {
|
||||
return nil, errors.New(status)
|
||||
}
|
||||
|
||||
a.mu.Lock()
|
||||
if a.client == nil {
|
||||
a.client = client
|
||||
a.connectionStatus = status
|
||||
a.mu.Unlock()
|
||||
return client, nil
|
||||
}
|
||||
existing := a.client
|
||||
a.mu.Unlock()
|
||||
|
||||
_ = client.Close()
|
||||
return existing, nil
|
||||
}
|
||||
|
||||
func (a *App) dropClient(client *grpcclient.Client) {
|
||||
a.mu.Lock()
|
||||
if a.client == client {
|
||||
a.client = nil
|
||||
a.connectionStatus = "модуль не подключен"
|
||||
}
|
||||
a.mu.Unlock()
|
||||
|
||||
if client != nil {
|
||||
_ = client.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) sendWithReconnect(build func() *pb.ClientMessage) (*pb.ServerMessage, error) {
|
||||
client, err := a.getClientOrConnect()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := client.Send(build())
|
||||
if err == nil {
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// stream умер (часто после рестарта демона) — сбрасываем и пробуем 1 раз заново
|
||||
a.dropClient(client)
|
||||
|
||||
client, err = a.getClientOrConnect()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return client.Send(build())
|
||||
}
|
||||
|
||||
func (a *App) getFrequency() string {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
return a.currentFrequency
|
||||
}
|
||||
|
||||
func (a *App) setFrequency(freq string) {
|
||||
a.mu.Lock()
|
||||
a.currentFrequency = freq
|
||||
a.mu.Unlock()
|
||||
}
|
||||
|
||||
func connectClient(ctx context.Context) (*grpcclient.Client, string) {
|
||||
cfg := config.Default()
|
||||
addr := cfg.GRPCAdvertiseAddr
|
||||
|
||||
discoveryCtx, cancel := context.WithTimeout(ctx, 2*time.Second)
|
||||
if discovered, err := discovery.Discover(discoveryCtx, cfg.DiscoveryPort); err == nil && discovered != "" {
|
||||
addr = discovered
|
||||
}
|
||||
cancel()
|
||||
|
||||
dialCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
//client, err := grpcclient.Dial(dialCtx, addr)
|
||||
client, err := grpcclient.Dial(dialCtx, HardAddr)
|
||||
if err != nil {
|
||||
log.Printf("gRPC connect failed: %v", err)
|
||||
return nil, "gRPC-клиент недоступен"
|
||||
}
|
||||
|
||||
log.Printf("connected to gRPC at %s", addr)
|
||||
return client, "модуль подключен"
|
||||
}
|
||||
|
||||
func requestID() string {
|
||||
return strconv.FormatInt(time.Now().UnixNano(), 10)
|
||||
}
|
||||
Reference in New Issue
Block a user