From bab44e7e3a04f9fa5bc567f7a388cf5062eb1cd6 Mon Sep 17 00:00:00 2001 From: huang <1724659546@qq.com> Date: Mon, 8 Sep 2025 10:58:26 +0800 Subject: [PATCH] =?UTF-8?q?1.=20=E5=A2=9E=E5=8A=A0=E7=A8=8B=E5=BA=8F?= =?UTF-8?q?=E5=90=AF=E5=8A=A8=E6=97=B6=E8=87=AA=E5=8A=A8=E8=BF=81=E7=A7=BB?= =?UTF-8?q?=E8=A1=A8=202.=20=E5=A2=9E=E5=8A=A0=E8=AE=BE=E5=A4=87=E4=BF=A1?= =?UTF-8?q?=E6=81=AFmodel=E5=92=8C=E5=9F=BA=E7=A1=80=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/api/api.go | 5 +- internal/controller/device/device.go | 24 ++++++-- internal/core/application.go | 9 ++- internal/model/device.go | 42 +++++++++++++- internal/storage/db/postgres.go | 17 ++++++ internal/storage/repository/device.go | 81 +++++++++++++++++++++++++++ 6 files changed, 168 insertions(+), 10 deletions(-) diff --git a/internal/api/api.go b/internal/api/api.go index a8022f8..7656b20 100644 --- a/internal/api/api.go +++ b/internal/api/api.go @@ -49,7 +49,7 @@ type API struct { // NewAPI 创建并返回一个新的API实例 // 初始化Gin引擎和相关配置 -func NewAPI(cfg *config.Config, userRepo repository.UserRepo, operationHistoryRepo repository.OperationHistoryRepo, deviceControlRepo repository.DeviceControlRepo) *API { +func NewAPI(cfg *config.Config, userRepo repository.UserRepo, operationHistoryRepo repository.OperationHistoryRepo, deviceControlRepo repository.DeviceControlRepo, deviceRepo repository.DeviceRepo) *API { // 设置Gin为发布模式 gin.SetMode(gin.ReleaseMode) @@ -80,7 +80,7 @@ func NewAPI(cfg *config.Config, userRepo repository.UserRepo, operationHistoryRe operationController := operation.NewController(operationHistoryRepo) // 创建设备控制控制器 - deviceController := device.NewController(deviceControlRepo) + deviceController := device.NewController(deviceControlRepo, deviceRepo) // 创建鉴权中间件 authMiddleware := middleware.NewAuthMiddleware(userRepo) @@ -170,7 +170,6 @@ func (a *API) setupRoutes() { { deviceGroup.POST("/switch", a.deviceController.Switch) } - } // TODO: 添加更多路由 diff --git a/internal/controller/device/device.go b/internal/controller/device/device.go index 117c534..7e2231b 100644 --- a/internal/controller/device/device.go +++ b/internal/controller/device/device.go @@ -15,20 +15,22 @@ import ( // Controller 设备控制控制器 type Controller struct { deviceControlRepo repository.DeviceControlRepo + deviceRepo repository.DeviceRepo logger *logs.Logger } // NewController 创建设备控制控制器实例 -func NewController(deviceControlRepo repository.DeviceControlRepo) *Controller { +func NewController(deviceControlRepo repository.DeviceControlRepo, deviceRepo repository.DeviceRepo) *Controller { return &Controller{ deviceControlRepo: deviceControlRepo, + deviceRepo: deviceRepo, logger: logs.NewLogger(), } } // ControlRequest 设备控制请求结构体 type ControlRequest struct { - PigPenID string `json:"pig_pen_id" binding:"required"` + 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"` @@ -55,13 +57,27 @@ func (c *Controller) Switch(ctx *gin.Context) { return } + // 获取区域主控设备信息(如果提供了ParentID) + var location string + if req.ParentID != nil { + parentDevice, err := c.deviceRepo.FindByID(*req.ParentID) + if err != nil { + c.logger.Error("查找区域主控设备失败: " + err.Error()) + ctx.JSON(http.StatusBadRequest, gin.H{"error": "无效的区域主控ID"}) + return + } + location = parentDevice.Name + } else { + location = "未知区域" + } + // TODO: 实际的设备控制逻辑 // 这里暂时用TODO代替具体逻辑 // 创建设备控制记录 control := &model.DeviceControl{ UserID: user.ID, - PigPenID: req.PigPenID, + Location: location, DeviceType: model.DeviceType(req.DeviceType), DeviceID: req.DeviceID, Action: req.Action, @@ -79,7 +95,7 @@ func (c *Controller) Switch(ctx *gin.Context) { "message": "设备控制成功", "data": map[string]interface{}{ "id": control.ID, - "pig_pen_id": control.PigPenID, + "location": control.Location, "device_type": control.DeviceType, "device_id": control.DeviceID, "action": control.Action, diff --git a/internal/core/application.go b/internal/core/application.go index 1eeaf69..a8d650d 100644 --- a/internal/core/application.go +++ b/internal/core/application.go @@ -35,6 +35,9 @@ type Application struct { // DeviceControlRepo 设备控制仓库实例 DeviceControlRepo repository.DeviceControlRepo + // DeviceRepo 设备仓库实例 + DeviceRepo repository.DeviceRepo + // Config 应用配置 Config *config.Config @@ -65,8 +68,11 @@ func NewApplication(cfg *config.Config) *Application { // 初始化设备控制仓库 deviceControlRepo := repository.NewDeviceControlRepo(store.GetDB()) + // 初始化设备仓库 + deviceRepo := repository.NewDeviceRepo(store.GetDB()) + // 初始化API组件 - apiInstance := api.NewAPI(cfg, userRepo, operationHistoryRepo, deviceControlRepo) + apiInstance := api.NewAPI(cfg, userRepo, operationHistoryRepo, deviceControlRepo, deviceRepo) // 初始化任务执行器组件(使用5个工作协程) taskExecutor := task.NewExecutor(5) @@ -78,6 +84,7 @@ func NewApplication(cfg *config.Config) *Application { UserRepo: userRepo, OperationHistoryRepo: operationHistoryRepo, DeviceControlRepo: deviceControlRepo, + DeviceRepo: deviceRepo, Config: cfg, logger: logs.NewLogger(), } diff --git a/internal/model/device.go b/internal/model/device.go index 8bbbc3a..649ff44 100644 --- a/internal/model/device.go +++ b/internal/model/device.go @@ -17,8 +17,46 @@ const ( // DeviceTypeWaterCurtain 水帘 DeviceTypeWaterCurtain DeviceType = "water_curtain" + + // DeviceTypePigPenController 猪舍主控 + DeviceTypePigPenController DeviceType = "pig_pen_controller" + + // DeviceTypeFeedMillController 做料车间主控 + DeviceTypeFeedMillController DeviceType = "feed_mill_controller" ) +// Device 代表设备信息 +type Device struct { + // ID 设备ID + ID uint `gorm:"primaryKey;column:id" json:"id"` + + // Name 设备名称 + Name string `gorm:"not null;column:name" json:"name"` + + // Type 设备类型 + Type DeviceType `gorm:"not null;column:type" json:"type"` + + // ParentID 上级设备ID(用于设备层级关系,指向区域主控设备) + ParentID *uint `gorm:"column:parent_id;index" json:"parent_id"` + + // Status 设备状态 + Status string `gorm:"not null;column:status" json:"status"` + + // CreatedAt 创建时间 + CreatedAt time.Time `gorm:"column:created_at" json:"created_at"` + + // UpdatedAt 更新时间 + UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"` + + // DeletedAt 删除时间(用于软删除) + DeletedAt gorm.DeletedAt `gorm:"index;column:deleted_at" json:"-"` +} + +// TableName 指定Device模型对应的数据库表名 +func (Device) TableName() string { + return "devices" +} + // DeviceControl 代表设备控制记录 type DeviceControl struct { // ID 记录ID @@ -27,8 +65,8 @@ type DeviceControl struct { // UserID 用户ID UserID uint `gorm:"not null;column:user_id;index" json:"user_id"` - // PigPenID 猪舍编号 - PigPenID string `gorm:"not null;column:pig_pen_id" json:"pig_pen_id"` + // Location 设备安装位置描述 + Location string `gorm:"not null;column:location" json:"location"` // DeviceType 设备类型 DeviceType DeviceType `gorm:"not null;column:device_type" json:"device_type"` diff --git a/internal/storage/db/postgres.go b/internal/storage/db/postgres.go index e5db9dc..9112640 100644 --- a/internal/storage/db/postgres.go +++ b/internal/storage/db/postgres.go @@ -8,10 +8,19 @@ import ( "time" "git.huangwc.com/pig/pig-farm-controller/internal/logs" + "git.huangwc.com/pig/pig-farm-controller/internal/model" "gorm.io/driver/postgres" "gorm.io/gorm" ) +// migrateModels 需要自动迁移的数据库模型列表 +var migrateModels = []interface{}{ + &model.User{}, + &model.OperationHistory{}, + &model.Device{}, + &model.DeviceControl{}, +} + // PostgresStorage 代表基于PostgreSQL的存储实现 // 使用GORM作为ORM库 type PostgresStorage struct { @@ -75,6 +84,14 @@ func (ps *PostgresStorage) Connect() error { sqlDB.SetMaxIdleConns(ps.maxIdleConns) sqlDB.SetConnMaxLifetime(time.Duration(ps.connMaxLifetime) * time.Second) + // 自动迁移数据库表结构 + ps.logger.Info("正在自动迁移数据库表结构") + if err = ps.db.AutoMigrate(migrateModels...); err != nil { + ps.logger.Error(fmt.Sprintf("数据库表结构迁移失败: %v", err)) + return fmt.Errorf("数据库表结构迁移失败: %v", err) + } + ps.logger.Info("数据库表结构迁移完成") + ps.logger.Info("PostgreSQL数据库连接成功") return nil } diff --git a/internal/storage/repository/device.go b/internal/storage/repository/device.go index 516a375..758335c 100644 --- a/internal/storage/repository/device.go +++ b/internal/storage/repository/device.go @@ -7,6 +7,27 @@ import ( "gorm.io/gorm" ) +// DeviceRepo 设备仓库接口 +type DeviceRepo interface { + // Create 创建设备 + Create(device *model.Device) error + + // FindByID 根据ID查找设备 + FindByID(id uint) (*model.Device, error) + + // FindByParentID 根据上级设备ID查找设备 + FindByParentID(parentID uint) ([]*model.Device, error) + + // FindByType 根据设备类型查找设备 + FindByType(deviceType model.DeviceType) ([]*model.Device, error) + + // Update 更新设备信息 + Update(device *model.Device) error + + // Delete 删除设备 + Delete(id uint) error +} + // DeviceControlRepo 设备控制仓库接口 type DeviceControlRepo interface { // Create 创建设备控制记录 @@ -22,11 +43,23 @@ type DeviceControlRepo interface { List(offset, limit int) ([]*model.DeviceControl, error) } +// deviceRepo 设备仓库实现 +type deviceRepo struct { + db *gorm.DB +} + // deviceControlRepo 设备控制仓库实现 type deviceControlRepo struct { db *gorm.DB } +// NewDeviceRepo 创建设备仓库实例 +func NewDeviceRepo(db *gorm.DB) DeviceRepo { + return &deviceRepo{ + db: db, + } +} + // NewDeviceControlRepo 创建设备控制仓库实例 func NewDeviceControlRepo(db *gorm.DB) DeviceControlRepo { return &deviceControlRepo{ @@ -34,6 +67,54 @@ func NewDeviceControlRepo(db *gorm.DB) DeviceControlRepo { } } +// Create 创建设备 +func (r *deviceRepo) Create(device *model.Device) error { + result := r.db.Create(device) + return result.Error +} + +// FindByID 根据ID查找设备 +func (r *deviceRepo) FindByID(id uint) (*model.Device, error) { + var device model.Device + result := r.db.First(&device, id) + if result.Error != nil { + return nil, result.Error + } + return &device, nil +} + +// FindByParentID 根据上级设备ID查找设备 +func (r *deviceRepo) FindByParentID(parentID uint) ([]*model.Device, error) { + var devices []*model.Device + result := r.db.Where("parent_id = ?", parentID).Find(&devices) + if result.Error != nil { + return nil, result.Error + } + return devices, nil +} + +// FindByType 根据设备类型查找设备 +func (r *deviceRepo) FindByType(deviceType model.DeviceType) ([]*model.Device, error) { + var devices []*model.Device + result := r.db.Where("type = ?", deviceType).Find(&devices) + if result.Error != nil { + return nil, result.Error + } + return devices, nil +} + +// Update 更新设备信息 +func (r *deviceRepo) Update(device *model.Device) error { + result := r.db.Save(device) + return result.Error +} + +// Delete 删除设备 +func (r *deviceRepo) Delete(id uint) error { + result := r.db.Delete(&model.Device{}, id) + return result.Error +} + // Create 创建设备控制记录 func (r *deviceControlRepo) Create(control *model.DeviceControl) error { result := r.db.Create(control)