From 085e8868e46c0b03342af5ee59eb9a59f6e163cf Mon Sep 17 00:00:00 2001 From: Eli Yip Date: Wed, 28 May 2025 16:52:48 +0800 Subject: [PATCH] feat: implement device handler --- api2/device_handlers.go | 251 ++++++++++++++++++++++++++++++++++++++++ define/hands.go | 16 ++- 2 files changed, 265 insertions(+), 2 deletions(-) create mode 100644 api2/device_handlers.go diff --git a/api2/device_handlers.go b/api2/device_handlers.go new file mode 100644 index 0000000..dce693b --- /dev/null +++ b/api2/device_handlers.go @@ -0,0 +1,251 @@ +package api2 + +import ( + "fmt" + "net/http" + + "hands/define" + "hands/device" + + "github.com/gin-gonic/gin" +) + +// handleGetDevices 获取所有设备列表 +func (s *Server) handleGetDevices(c *gin.Context) { + devices := s.deviceManager.GetAllDevices() + + deviceInfos := make([]DeviceInfo, 0, len(devices)) + for _, dev := range devices { + status, err := dev.GetStatus() + if err != nil { + // 如果获取状态失败,使用默认状态 + status = device.DeviceStatus{ + IsConnected: false, + IsActive: false, + ErrorCount: 1, + LastError: err.Error(), + } + } + + deviceInfo := DeviceInfo{ + ID: dev.GetID(), + Model: dev.GetModel(), + HandType: dev.GetHandType().String(), + Status: status, + } + deviceInfos = append(deviceInfos, deviceInfo) + } + + response := DeviceListResponse{ + Devices: deviceInfos, + Total: len(deviceInfos), + } + + c.JSON(http.StatusOK, ApiResponse{ + Status: "success", + Data: response, + }) +} + +// handleCreateDevice 创建新设备 +func (s *Server) handleCreateDevice(c *gin.Context) { + var req DeviceCreateRequest + if err := c.ShouldBindJSON(&req); err != nil { + c.JSON(http.StatusBadRequest, ApiResponse{ + Status: "error", + Error: "无效的设备创建请求:" + err.Error(), + }) + return + } + + // 检查设备是否已存在 + if _, err := s.deviceManager.GetDevice(req.ID); err == nil { + c.JSON(http.StatusConflict, ApiResponse{ + Status: "error", + Error: fmt.Sprintf("设备 %s 已存在", req.ID), + }) + return + } + + // 准备设备配置 + config := req.Config + if config == nil { + config = make(map[string]any) + } + config["id"] = req.ID + + // 设置手型 + if req.HandType != "" { + config["hand_type"] = req.HandType + } + + // 创建设备实例 + dev, err := device.CreateDevice(req.Model, config) + if err != nil { + c.JSON(http.StatusBadRequest, ApiResponse{ + Status: "error", + Error: fmt.Sprintf("创建设备失败:%v", err), + }) + return + } + + // 注册设备到管理器 + if err := s.deviceManager.RegisterDevice(dev); err != nil { + c.JSON(http.StatusInternalServerError, ApiResponse{ + Status: "error", + Error: fmt.Sprintf("注册设备失败:%v", err), + }) + return + } + + // 获取设备状态 + status, err := dev.GetStatus() + if err != nil { + status = device.DeviceStatus{ + IsConnected: false, + IsActive: false, + ErrorCount: 1, + LastError: err.Error(), + } + } + + deviceInfo := DeviceInfo{ + ID: dev.GetID(), + Model: dev.GetModel(), + HandType: dev.GetHandType().String(), + Status: status, + } + + c.JSON(http.StatusCreated, ApiResponse{ + Status: "success", + Message: fmt.Sprintf("设备 %s 创建成功", req.ID), + Data: deviceInfo, + }) +} + +// handleGetDevice 获取设备详情 +func (s *Server) handleGetDevice(c *gin.Context) { + deviceId := c.Param("deviceId") + + dev, err := s.deviceManager.GetDevice(deviceId) + if err != nil { + c.JSON(http.StatusNotFound, ApiResponse{ + Status: "error", + Error: fmt.Sprintf("设备 %s 不存在", deviceId), + }) + return + } + + status, err := dev.GetStatus() + if err != nil { + status = device.DeviceStatus{ + IsConnected: false, + IsActive: false, + ErrorCount: 1, + LastError: err.Error(), + } + } + + deviceInfo := DeviceInfo{ + ID: dev.GetID(), + Model: dev.GetModel(), + HandType: dev.GetHandType().String(), + Status: status, + } + + c.JSON(http.StatusOK, ApiResponse{ + Status: "success", + Data: deviceInfo, + }) +} + +// handleDeleteDevice 删除设备 +func (s *Server) handleDeleteDevice(c *gin.Context) { + deviceId := c.Param("deviceId") + + // 检查设备是否存在 + dev, err := s.deviceManager.GetDevice(deviceId) + if err != nil { + c.JSON(http.StatusNotFound, ApiResponse{ + Status: "error", + Error: fmt.Sprintf("设备 %s 不存在", deviceId), + }) + return + } + + // 停止设备的动画(如果正在运行) + animEngine := dev.GetAnimationEngine() + if animEngine.IsRunning() { + if err := animEngine.Stop(); err != nil { + // 记录错误但不阻止删除 + fmt.Printf("警告:停止设备 %s 动画时出错:%v\n", deviceId, err) + } + } + + // 从管理器中移除设备 + if err := s.deviceManager.RemoveDevice(deviceId); err != nil { + c.JSON(http.StatusInternalServerError, ApiResponse{ + Status: "error", + Error: fmt.Sprintf("删除设备失败:%v", err), + }) + return + } + + c.JSON(http.StatusOK, ApiResponse{ + Status: "success", + Message: fmt.Sprintf("设备 %s 已删除", deviceId), + }) +} + +// handleSetHandType 设置设备手型 +func (s *Server) handleSetHandType(c *gin.Context) { + deviceId := c.Param("deviceId") + + var req HandTypeRequest + if err := c.ShouldBindJSON(&req); err != nil { + c.JSON(http.StatusBadRequest, ApiResponse{ + Status: "error", + Error: "无效的手型设置请求:" + err.Error(), + }) + return + } + + // 获取设备 + dev, err := s.deviceManager.GetDevice(deviceId) + if err != nil { + c.JSON(http.StatusNotFound, ApiResponse{ + Status: "error", + Error: fmt.Sprintf("设备 %s 不存在", deviceId), + }) + return + } + + // 转换手型字符串为枚举 + var handType define.HandType + handType = define.HandTypeFromString(req.HandType) + if handType == define.HAND_TYPE_UNKNOWN { + c.JSON(http.StatusBadRequest, ApiResponse{ + Status: "error", + Error: "无效的手型,必须是 'left' 或 'right'", + }) + return + } + + // 设置手型 + if err := dev.SetHandType(handType); err != nil { + c.JSON(http.StatusInternalServerError, ApiResponse{ + Status: "error", + Error: fmt.Sprintf("设置手型失败:%v", err), + }) + return + } + + c.JSON(http.StatusOK, ApiResponse{ + Status: "success", + Message: fmt.Sprintf("设备 %s 手型已设置为 %s", deviceId, req.HandType), + Data: map[string]any{ + "deviceId": deviceId, + "handType": req.HandType, + }, + }) +} diff --git a/define/hands.go b/define/hands.go index fb821ae..04e3c8e 100644 --- a/define/hands.go +++ b/define/hands.go @@ -3,8 +3,9 @@ package define type HandType int const ( - HAND_TYPE_LEFT HandType = 0x28 - HAND_TYPE_RIGHT HandType = 0x27 + HAND_TYPE_LEFT HandType = 0x28 + HAND_TYPE_RIGHT HandType = 0x27 + HAND_TYPE_UNKNOWN HandType = 0x00 ) func (ht HandType) String() string { @@ -13,3 +14,14 @@ func (ht HandType) String() string { } return "右手" } + +func HandTypeFromString(s string) HandType { + switch s { + case "left": + return HAND_TYPE_LEFT + case "right": + return HAND_TYPE_RIGHT + default: + return HAND_TYPE_UNKNOWN + } +}