This commit is contained in:
2026-08-27 19:41:00 +03:00
parent de0e8f8ad3
commit 0d80f575c1
389 changed files with 183499 additions and 0 deletions
+287
View File
@@ -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)
}