feat: implement legacy status api

This commit is contained in:
Eli Yip 2025-06-04 09:51:00 +08:00
parent f8aa2138ab
commit 200f2e1751
No known key found for this signature in database
GPG Key ID: C98B69D4CF7D7EC5
4 changed files with 47 additions and 57 deletions

View File

@ -508,6 +508,13 @@ func (s *LegacyServer) handleStatus(c *gin.Context) {
// 检查 CAN 服务状态 - 通过尝试获取设备状态来判断 // 检查 CAN 服务状态 - 通过尝试获取设备状态来判断
canStatus := make(map[string]bool) canStatus := make(map[string]bool)
for ifName, handConfig := range allHandConfigs {
handConfigsData[ifName] = map[string]any{
"handType": handConfig.HandType,
"handId": handConfig.HandId,
}
}
for _, ifName := range config.Config.AvailableInterfaces { for _, ifName := range config.Config.AvailableInterfaces {
// 获取对应的设备 // 获取对应的设备
dev, err := s.mapper.GetDeviceForInterface(ifName) dev, err := s.mapper.GetDeviceForInterface(ifName)
@ -525,32 +532,11 @@ func (s *LegacyServer) handleStatus(c *gin.Context) {
animationStatus[ifName] = animEngine.IsRunning() animationStatus[ifName] = animEngine.IsRunning()
// 获取设备状态来判断 CAN 服务状态 // 获取设备状态来判断 CAN 服务状态
status, err := dev.GetStatus() rawCanStatus, err := dev.GetCanStatus()
if err != nil { if err != nil {
canStatus[ifName] = false canStatus[ifName] = false
} else { } else {
canStatus[ifName] = status.IsConnected && status.IsActive canStatus[ifName] = rawCanStatus[ifName]
}
// 获取手型配置
if handConfig, exists := allHandConfigs[ifName]; exists {
handConfigsData[ifName] = map[string]any{
"handType": handConfig.HandType,
"handId": handConfig.HandId,
}
} else {
// 从设备获取当前手型
handType := dev.GetHandType()
handTypeStr := "right"
handId := uint32(define.HAND_TYPE_RIGHT)
if handType == define.HAND_TYPE_LEFT {
handTypeStr = "left"
handId = uint32(define.HAND_TYPE_LEFT)
}
handConfigsData[ifName] = map[string]any{
"handType": handTypeStr,
"handId": handId,
}
} }
} }

View File

@ -5,6 +5,8 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"hands/config"
"hands/define"
"io" "io"
"net/http" "net/http"
"time" "time"
@ -23,9 +25,6 @@ type Communicator interface {
// SendMessage 将 RawMessage 通过 HTTP POST 请求发送到 can-bridge 服务 // SendMessage 将 RawMessage 通过 HTTP POST 请求发送到 can-bridge 服务
SendMessage(ctx context.Context, msg RawMessage) error SendMessage(ctx context.Context, msg RawMessage) error
// GetInterfaceStatus 获取指定 CAN 接口的状态
GetInterfaceStatus(ifName string) (isActive bool, err error)
// GetAllInterfaceStatuses 获取所有已知 CAN 接口的状态 // GetAllInterfaceStatuses 获取所有已知 CAN 接口的状态
GetAllInterfaceStatuses() (statuses map[string]bool, err error) GetAllInterfaceStatuses() (statuses map[string]bool, err error)
@ -45,9 +44,7 @@ type CanBridgeClient struct {
func NewCanBridgeClient(serviceURL string) Communicator { func NewCanBridgeClient(serviceURL string) Communicator {
return &CanBridgeClient{ return &CanBridgeClient{
serviceURL: serviceURL, serviceURL: serviceURL,
client: &http.Client{ client: &http.Client{Timeout: 5 * time.Second},
Timeout: 5 * time.Second,
},
} }
} }
@ -60,7 +57,7 @@ func (c *CanBridgeClient) SendMessage(ctx context.Context, msg RawMessage) error
url := fmt.Sprintf("%s/api/can", c.serviceURL) url := fmt.Sprintf("%s/api/can", c.serviceURL)
// 创建带有 context 的请求 // 创建带有 context 的请求
req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(jsonData)) req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewBuffer(jsonData))
if err != nil { if err != nil {
return fmt.Errorf("创建 HTTP 请求失败:%w", err) return fmt.Errorf("创建 HTTP 请求失败:%w", err)
} }
@ -80,47 +77,49 @@ func (c *CanBridgeClient) SendMessage(ctx context.Context, msg RawMessage) error
return nil return nil
} }
func (c *CanBridgeClient) GetInterfaceStatus(ifName string) (bool, error) {
url := fmt.Sprintf("%s/api/status/%s", c.serviceURL, ifName)
resp, err := c.client.Get(url)
if err != nil {
return false, fmt.Errorf("获取接口状态失败:%w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return false, fmt.Errorf("can-bridge 服务返回错误:%d", resp.StatusCode)
}
var status struct {
Active bool `json:"active"`
}
if err := json.NewDecoder(resp.Body).Decode(&status); err != nil {
return false, fmt.Errorf("解析状态响应失败:%w", err)
}
return status.Active, nil
}
func (c *CanBridgeClient) GetAllInterfaceStatuses() (map[string]bool, error) { func (c *CanBridgeClient) GetAllInterfaceStatuses() (map[string]bool, error) {
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
url := fmt.Sprintf("%s/api/status", c.serviceURL) url := fmt.Sprintf("%s/api/status", c.serviceURL)
resp, err := c.client.Get(url) req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil { if err != nil {
return nil, fmt.Errorf("获取所有接口状态失败:%w", err) return nil, fmt.Errorf("获取所有接口状态失败:%w", err)
} }
resp, err := c.client.Do(req)
if err != nil {
return nil, fmt.Errorf("发送 HTTP 请求失败:%w", err)
}
defer resp.Body.Close() defer resp.Body.Close()
if resp.StatusCode != http.StatusOK { if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("can-bridge 服务返回错误:%d", resp.StatusCode) return nil, fmt.Errorf("can-bridge 服务返回错误:%d", resp.StatusCode)
} }
var statuses map[string]bool var statusResp define.ApiResponse
if err := json.NewDecoder(resp.Body).Decode(&statuses); err != nil { if err := json.NewDecoder(resp.Body).Decode(&statusResp); err != nil {
return nil, fmt.Errorf("解析状态响应失败:%w", err) return nil, fmt.Errorf("解析状态响应失败:%w", err)
} }
return statuses, nil result := make(map[string]bool)
for _, ifName := range config.Config.AvailableInterfaces {
result[ifName] = false
}
if statusData, ok := statusResp.Data.(map[string]interface{}); ok {
if interfaces, ok := statusData["interfaces"].(map[string]interface{}); ok {
for ifName, ifStatus := range interfaces {
if status, ok := ifStatus.(map[string]interface{}); ok {
if active, ok := status["active"].(bool); ok {
result[ifName] = active
}
}
}
}
}
return result, nil
} }
func (c *CanBridgeClient) SetServiceURL(url string) { c.serviceURL = url } func (c *CanBridgeClient) SetServiceURL(url string) { c.serviceURL = url }

View File

@ -14,6 +14,7 @@ type Device interface {
ExecuteCommand(cmd Command) error // 执行一个通用指令 ExecuteCommand(cmd Command) error // 执行一个通用指令
ReadSensorData() (SensorData, error) // 读取特定传感器数据 ReadSensorData() (SensorData, error) // 读取特定传感器数据
GetComponents(componentType ComponentType) []Component // 获取指定类型的组件 GetComponents(componentType ComponentType) []Component // 获取指定类型的组件
GetCanStatus() (map[string]bool, error)
GetStatus() (DeviceStatus, error) // 获取设备状态 GetStatus() (DeviceStatus, error) // 获取设备状态
Connect() error // 连接设备 Connect() error // 连接设备
Disconnect() error // 断开设备连接 Disconnect() error // 断开设备连接

View File

@ -372,3 +372,7 @@ func (h *L10Hand) GetPresetDescription(presetName string) string {
func (h *L10Hand) GetPresetDetails(presetName string) (device.PresetPose, bool) { func (h *L10Hand) GetPresetDetails(presetName string) (device.PresetPose, bool) {
return h.presetManager.GetPreset(presetName) return h.presetManager.GetPreset(presetName)
} }
func (h *L10Hand) GetCanStatus() (map[string]bool, error) {
return h.communicator.GetAllInterfaceStatuses()
}