// Package device 提供设备控制相关功能的控制器 // 实现设备控制、查询等操作 package device import ( "git.huangwc.com/pig/pig-farm-controller/internal/api/middleware" "git.huangwc.com/pig/pig-farm-controller/internal/controller" "git.huangwc.com/pig/pig-farm-controller/internal/logs" "git.huangwc.com/pig/pig-farm-controller/internal/model" "git.huangwc.com/pig/pig-farm-controller/internal/service" "git.huangwc.com/pig/pig-farm-controller/internal/storage/repository" "github.com/gin-gonic/gin" ) // Controller 设备控制控制器 type Controller struct { deviceControlRepo repository.DeviceControlRepo deviceRepo repository.DeviceRepo websocketService *service.WebSocketService logger *logs.Logger } // NewController 创建设备控制控制器实例 func NewController(deviceControlRepo repository.DeviceControlRepo, deviceRepo repository.DeviceRepo, websocketService *service.WebSocketService) *Controller { return &Controller{ deviceControlRepo: deviceControlRepo, deviceRepo: deviceRepo, websocketService: websocketService, logger: logs.NewLogger(), } } // SwitchRequest 设备控制请求结构体 type SwitchRequest struct { ParentID *uint `json:"parent_id"` // 区域主控ID DeviceType string `json:"device_type" binding:"required,oneof=fan water_curtain"` DeviceID string `json:"device_id" binding:"required"` Action string `json:"action" binding:"required,oneof=on off"` } // SwitchResponseData 设备控制响应数据结构体 type SwitchResponseData struct { DeviceType string `json:"device_type"` DeviceID string `json:"device_id"` Action string `json:"action"` Status string `json:"status"` // 添加状态字段 Message string `json:"message"` // 添加消息字段 } // RelayControlData 发送给中继设备的控制数据结构体 type RelayControlData struct { DeviceType string `json:"device_type"` DeviceID string `json:"device_id"` Action string `json:"action"` } // RelayControlResponseData 中继设备控制响应数据结构体 type RelayControlResponseData struct { Status string `json:"status"` Message string `json:"message"` } // Switch 设备控制接口 func (c *Controller) Switch(ctx *gin.Context) { // 从上下文中获取用户信息 userValue, exists := ctx.Get("user") if !exists { controller.SendErrorResponse(ctx, controller.UnauthorizedCode, "无法获取用户信息") return } user, ok := userValue.(*middleware.AuthUser) if !ok { controller.SendErrorResponse(ctx, controller.InternalServerErrorCode, "用户信息格式错误") return } var req SwitchRequest if err := ctx.ShouldBindJSON(&req); err != nil { controller.SendErrorResponse(ctx, controller.InvalidParameterCode, "请求参数错误") return } // 通过WebSocket向中继设备发送控制指令 controlData := RelayControlData{ DeviceType: req.DeviceType, DeviceID: req.DeviceID, Action: req.Action, } // 发送指令并等待响应 response, err := c.websocketService.SendCommandAndWait("relay-001", "control_device", controlData, 0) if err != nil { c.logger.Error("通过WebSocket发送设备控制指令失败: " + err.Error()) controller.SendErrorResponse(ctx, controller.InternalServerErrorCode, "设备控制失败: "+err.Error()) return } // 使用响应中的状态和消息 status := "解析失败" message := "消息解析失败" // 如果响应中没有明确的状态和消息,则从数据中提取 if status == "" && message == "" { // 解析响应数据 var responseData RelayControlResponseData if err := response.ParseData(&responseData); err == nil { status = responseData.Status message = responseData.Message } } // 创建设备控制记录 if err := c.createDeviceControlRecord( user.ID, req.DeviceID, req.DeviceType, req.Action, status, message, ); err != nil { c.logger.Error("创建设备控制记录失败: " + err.Error()) controller.SendErrorResponse(ctx, controller.InternalServerErrorCode, "记录控制历史失败") return } data := SwitchResponseData{ DeviceType: req.DeviceType, DeviceID: req.DeviceID, Action: req.Action, Status: status, Message: message, } controller.SendSuccessResponse(ctx, "设备控制成功", data) } // createDeviceControlRecord 创建设备控制记录 func (c *Controller) createDeviceControlRecord(userID uint, deviceID, deviceType, action, status, result string) error { // 获取设备信息 device, err := c.deviceRepo.FindByIDString(deviceID) if err != nil { return err } // 构建位置信息 var location string switch device.Type { case model.DeviceTypeRelay: // 如果设备本身就是中继设备 location = device.Name case model.DeviceTypePigPenController, model.DeviceTypeFeedMillController: // 如果设备本身就是区域主控设备 if device.ParentID != nil { // 获取中继设备 relayDevice, err := c.deviceRepo.FindByID(*device.ParentID) if err != nil { location = device.Name } else { location = relayDevice.Name + " -> " + device.Name } } else { location = device.Name } default: // 如果是普通设备(风机、水帘等) if device.ParentID != nil { // 获取区域主控设备 parentDevice, err := c.deviceRepo.FindByID(*device.ParentID) if err != nil { location = "未知区域" } else { // 检查区域主控设备是否有上级设备(中继设备) if parentDevice.ParentID != nil { // 获取中继设备 relayDevice, err := c.deviceRepo.FindByID(*parentDevice.ParentID) if err != nil { location = parentDevice.Name } else { location = relayDevice.Name + " -> " + parentDevice.Name } } else { location = parentDevice.Name } } } else { location = "未知区域" } } control := &model.DeviceControl{ UserID: userID, Location: location, DeviceType: model.DeviceType(deviceType), DeviceID: deviceID, Action: action, Status: status, Result: result, } return c.deviceControlRepo.Create(control) }