// 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" ) // ListResponse 设备列表响应结构体 type ListResponse struct { Devices []model.Device `json:"devices"` } // DeviceRequest 设备创建/更新请求结构体 type DeviceRequest struct { Name string `json:"name" binding:"required"` Type model.DeviceType `json:"type" binding:"required"` ParentID *uint `json:"parent_id"` Status string `json:"status" binding:"required"` } // 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(), } } // List 获取设备列表 func (c *Controller) List(ctx *gin.Context) { devices, err := c.deviceRepo.ListAll() if err != nil { c.logger.Error("获取设备列表失败: " + err.Error()) controller.SendErrorResponse(ctx, controller.InternalServerErrorCode, "获取设备列表失败") return } controller.SendSuccessResponse(ctx, "获取设备列表成功", ListResponse{Devices: devices}) } // Create 创建设备 func (c *Controller) Create(ctx *gin.Context) { var req DeviceRequest if err := ctx.ShouldBindJSON(&req); err != nil { controller.SendErrorResponse(ctx, controller.InvalidParameterCode, "请求参数错误: "+err.Error()) return } device := &model.Device{ Name: req.Name, Type: req.Type, ParentID: req.ParentID, Status: req.Status, } if err := c.deviceRepo.Create(device); err != nil { c.logger.Error("创建设备失败: " + err.Error()) controller.SendErrorResponse(ctx, controller.InternalServerErrorCode, "创建设备失败") return } controller.SendSuccessResponse(ctx, "创建设备成功", device) } // Update 更新设备 func (c *Controller) Update(ctx *gin.Context) { var req struct { ID uint `json:"id" binding:"required"` DeviceRequest } if err := ctx.ShouldBindJSON(&req); err != nil { controller.SendErrorResponse(ctx, controller.InvalidParameterCode, "请求参数错误: "+err.Error()) return } device, err := c.deviceRepo.FindByID(req.ID) if err != nil { c.logger.Error("查找设备失败: " + err.Error()) controller.SendErrorResponse(ctx, controller.NotFoundCode, "设备不存在") return } device.Name = req.Name device.Type = req.Type device.ParentID = req.ParentID device.Status = req.Status if err := c.deviceRepo.Update(device); err != nil { c.logger.Error("更新设备失败: " + err.Error()) controller.SendErrorResponse(ctx, controller.InternalServerErrorCode, "更新设备失败") return } controller.SendSuccessResponse(ctx, "更新设备成功", device) } // Delete 删除设备 func (c *Controller) Delete(ctx *gin.Context) { var req struct { ID uint `json:"id" binding:"required"` } if err := ctx.ShouldBindJSON(&req); err != nil { controller.SendErrorResponse(ctx, controller.InvalidParameterCode, "请求参数错误: "+err.Error()) return } // 先检查设备是否存在 _, err := c.deviceRepo.FindByID(req.ID) if err != nil { c.logger.Error("查找设备失败: " + err.Error()) controller.SendErrorResponse(ctx, controller.NotFoundCode, "设备不存在") return } if err := c.deviceRepo.Delete(req.ID); err != nil { c.logger.Error("删除设备失败: " + err.Error()) controller.SendErrorResponse(ctx, controller.InternalServerErrorCode, "删除设备失败") return } controller.SendSuccessResponse(ctx, "删除设备成功", nil) } // 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 := "消息解析失败" 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) }