Files
pig-farm-controller/internal/app/dto/device_converter.go

154 lines
4.8 KiB
Go
Raw Normal View History

2025-10-03 23:02:43 +08:00
package dto
import (
"fmt"
"time"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
)
// NewDeviceResponse 从数据库模型创建一个新的设备响应 DTO
func NewDeviceResponse(device *models.Device) (*DeviceResponse, error) {
if device == nil {
return nil, nil
}
var props map[string]interface{}
if len(device.Properties) > 0 && string(device.Properties) != "null" {
if err := device.ParseProperties(&props); err != nil {
return nil, fmt.Errorf("解析设备属性失败 (ID: %d): %w", device.ID, err)
}
}
// 确保 DeviceTemplate 和 AreaController 已预加载
deviceTemplateName := ""
if device.DeviceTemplate.ID != 0 {
deviceTemplateName = device.DeviceTemplate.Name
}
areaControllerName := ""
if device.AreaController.ID != 0 {
areaControllerName = device.AreaController.Name
}
return &DeviceResponse{
ID: device.ID,
Name: device.Name,
DeviceTemplateID: device.DeviceTemplateID,
DeviceTemplateName: deviceTemplateName,
AreaControllerID: device.AreaControllerID,
AreaControllerName: areaControllerName,
Location: device.Location,
Properties: props,
CreatedAt: device.CreatedAt.Format(time.RFC3339),
UpdatedAt: device.UpdatedAt.Format(time.RFC3339),
}, nil
}
// NewListDeviceResponse 从数据库模型切片创建一个新的设备列表响应 DTO 切片
func NewListDeviceResponse(devices []*models.Device) ([]*DeviceResponse, error) {
list := make([]*DeviceResponse, 0, len(devices))
for _, device := range devices {
resp, err := NewDeviceResponse(device)
if err != nil {
return nil, err
}
list = append(list, resp)
}
return list, nil
}
// NewAreaControllerResponse 从数据库模型创建一个新的区域主控响应 DTO
func NewAreaControllerResponse(ac *models.AreaController) (*AreaControllerResponse, error) {
if ac == nil {
return nil, nil
}
2025-12-01 17:49:30 +08:00
// 解析 firmware_version
var firmwareVersion string
// 使用模型上的辅助方法来解析强类型属性
acProps := &models.AreaControllerProperties{}
if err := ac.ParseProperties(acProps); err == nil {
firmwareVersion = acProps.FirmwareVersion
}
// 如果解析出错firmwareVersion 将保持为空字符串,这通常是可接受的降级行为
// 解析完整的 properties 以便向后兼容或用于其他未知属性
var allProps map[string]interface{}
2025-10-03 23:02:43 +08:00
if len(ac.Properties) > 0 && string(ac.Properties) != "null" {
2025-12-01 17:49:30 +08:00
// 这里我们使用通用的 ParseProperties 方法
if err := ac.ParseProperties(&allProps); err != nil {
return nil, fmt.Errorf("解析区域主控完整属性失败 (ID: %d): %w", ac.ID, err)
2025-10-03 23:02:43 +08:00
}
}
return &AreaControllerResponse{
2025-12-01 17:49:30 +08:00
ID: ac.ID,
Name: ac.Name,
NetworkID: ac.NetworkID,
FirmwareVersion: firmwareVersion,
Location: ac.Location,
Status: ac.Status,
Properties: allProps, // 填充完整的 properties
CreatedAt: ac.CreatedAt.Format(time.RFC3339),
UpdatedAt: ac.UpdatedAt.Format(time.RFC3339),
2025-10-03 23:02:43 +08:00
}, nil
}
// NewListAreaControllerResponse 从数据库模型切片创建一个新的区域主控列表响应 DTO 切片
func NewListAreaControllerResponse(acs []*models.AreaController) ([]*AreaControllerResponse, error) {
list := make([]*AreaControllerResponse, 0, len(acs))
for _, ac := range acs {
resp, err := NewAreaControllerResponse(ac)
if err != nil {
return nil, err
}
list = append(list, resp)
}
return list, nil
}
// NewDeviceTemplateResponse 从数据库模型创建一个新的设备模板响应 DTO
func NewDeviceTemplateResponse(dt *models.DeviceTemplate) (*DeviceTemplateResponse, error) {
if dt == nil {
return nil, nil
}
var commands map[string]interface{}
if err := dt.ParseCommands(&commands); err != nil {
return nil, fmt.Errorf("解析设备模板命令失败 (ID: %d): %w", dt.ID, err)
}
var values []models.ValueDescriptor
if dt.Category == models.CategorySensor {
if err := dt.ParseValues(&values); err != nil {
return nil, fmt.Errorf("解析设备模板值描述符失败 (ID: %d): %w", dt.ID, err)
}
}
return &DeviceTemplateResponse{
ID: dt.ID,
Name: dt.Name,
Manufacturer: dt.Manufacturer,
Description: dt.Description,
Category: dt.Category,
Commands: commands,
Values: values,
CreatedAt: dt.CreatedAt.Format(time.RFC3339),
UpdatedAt: dt.UpdatedAt.Format(time.RFC3339),
}, nil
}
// NewListDeviceTemplateResponse 从数据库模型切片创建一个新的设备模板列表响应 DTO 切片
func NewListDeviceTemplateResponse(dts []*models.DeviceTemplate) ([]*DeviceTemplateResponse, error) {
list := make([]*DeviceTemplateResponse, 0, len(dts))
for _, dt := range dts {
resp, err := NewDeviceTemplateResponse(dt)
if err != nil {
return nil, err
}
list = append(list, resp)
}
return list, nil
}