| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347 |
- package device
- import (
- "context"
- "fmt"
- "time"
- "iot-base-station/pkg/database"
- "iot-base-station/pkg/security"
- "github.com/go-redis/redis/v8"
- "go.uber.org/zap"
- "gorm.io/gorm"
- )
- // Manager 设备管理器
- type Manager struct {
- db *gorm.DB
- redis *redis.Client
- logger *zap.Logger
- }
- // NewManager 创建设备管理器
- func NewManager(db *gorm.DB, redis *redis.Client, logger *zap.Logger) *Manager {
- return &Manager{
- db: db,
- redis: redis,
- logger: logger,
- }
- }
- // CreateDevice 创建设备
- func (m *Manager) CreateDevice(ctx context.Context, req *CreateDeviceRequest) (*DeviceResponse, error) {
- // 生成设备ID
- deviceID := generateDeviceID(req.Type)
- // 创建设备对象
- device := &Device{
- ID: deviceID,
- Name: req.Name,
- Type: req.Type,
- Protocol: req.Protocol,
- Status: StatusOffline,
- Metadata: req.Metadata,
- Config: req.Config,
- Location: req.Location,
- Firmware: FirmwareInfo{
- Version: "1.0.0",
- ReleaseDate: time.Now(),
- },
- }
- // 保存到数据库
- if err := m.db.WithContext(ctx).Create(device).Error; err != nil {
- m.logger.Error("Failed to create device", zap.Error(err))
- return nil, fmt.Errorf("failed to create device: %w", err)
- }
- // 创建设备事件
- event := &DeviceEvent{
- ID: generateEventID(),
- DeviceID: deviceID,
- Type: EventConnect,
- Severity: SeverityInfo,
- Message: "设备已创建",
- Timestamp: time.Now(),
- }
- if err := m.db.WithContext(ctx).Create(event).Error; err != nil {
- m.logger.Error("Failed to create device event", zap.Error(err))
- }
- m.logger.Info("Device created", zap.String("device_id", deviceID))
- return &device.ToResponse(), nil
- }
- // ListDevices 获取设备列表
- func (m *Manager) ListDevices(ctx context.Context, page, pageSize int, deviceType string) ([]DeviceResponse, int64, error) {
- var devices []Device
- var total int64
- query := m.db.WithContext(ctx).Model(&Device{})
- // 按类型筛选
- if deviceType != "" {
- query = query.Where("type = ?", deviceType)
- }
- // 获取总数
- if err := query.Count(&total).Error; err != nil {
- m.logger.Error("Failed to count devices", zap.Error(err))
- return nil, 0, fmt.Errorf("failed to count devices: %w", err)
- }
- // 分页查询
- offset := (page - 1) * pageSize
- if err := query.Offset(offset).Limit(pageSize).Find(&devices).Error; err != nil {
- m.logger.Error("Failed to list devices", zap.Error(err))
- return nil, 0, fmt.Errorf("failed to list devices: %w", err)
- }
- // 转换为响应格式
- responses := make([]DeviceResponse, len(devices))
- for i, device := range devices {
- responses[i] = device.ToResponse()
- }
- return responses, total, nil
- }
- // GetDevice 获取设备详情
- func (m *Manager) GetDevice(ctx context.Context, deviceID string) (*DeviceResponse, error) {
- var device Device
- if err := m.db.WithContext(ctx).Where("id = ?", deviceID).First(&device).Error; err != nil {
- if err == gorm.ErrRecordNotFound {
- return nil, fmt.Errorf("device not found")
- }
- m.logger.Error("Failed to get device", zap.Error(err))
- return nil, fmt.Errorf("failed to get device: %w", err)
- }
- return &device.ToResponse(), nil
- }
- // UpdateDevice 更新设备信息
- func (m *Manager) UpdateDevice(ctx context.Context, deviceID string, req *UpdateDeviceRequest) (*DeviceResponse, error) {
- var device Device
- // 查询设备
- if err := m.db.WithContext(ctx).Where("id = ?", deviceID).First(&device).Error; err != nil {
- if err == gorm.ErrRecordNotFound {
- return nil, fmt.Errorf("device not found")
- }
- m.logger.Error("Failed to get device", zap.Error(err))
- return nil, fmt.Errorf("failed to get device: %w", err)
- }
- // 更新字段
- if req.Name != "" {
- device.Name = req.Name
- }
- if req.Metadata != nil {
- device.Metadata = req.Metadata
- }
- if req.Config.ReportInterval > 0 {
- device.Config.ReportInterval = req.Config.ReportInterval
- }
- if req.Config.Threshold != nil {
- device.Config.Threshold = req.Config.Threshold
- }
- if req.Location.Address != "" {
- device.Location = req.Location
- }
- // 保存更新
- if err := m.db.WithContext(ctx).Save(&device).Error; err != nil {
- m.logger.Error("Failed to update device", zap.Error(err))
- return nil, fmt.Errorf("failed to update device: %w", err)
- }
- // 创建配置更新事件
- event := &DeviceEvent{
- ID: generateEventID(),
- DeviceID: deviceID,
- Type: EventConfig,
- Severity: SeverityInfo,
- Message: "设备配置已更新",
- Timestamp: time.Now(),
- }
- if err := m.db.WithContext(ctx).Create(event).Error; err != nil {
- m.logger.Error("Failed to create device event", zap.Error(err))
- }
- m.logger.Info("Device updated", zap.String("device_id", deviceID))
- return &device.ToResponse(), nil
- }
- // DeleteDevice 删除设备
- func (m *Manager) DeleteDevice(ctx context.Context, deviceID string) error {
- // 软删除设备
- if err := m.db.WithContext(ctx).Delete(&Device{}, "id = ?", deviceID).Error; err != nil {
- m.logger.Error("Failed to delete device", zap.Error(err))
- return fmt.Errorf("failed to delete device: %w", err)
- }
- m.logger.Info("Device deleted", zap.String("device_id", deviceID))
- return nil
- }
- // UpdateDeviceConfig 更新设备配置
- func (m *Manager) UpdateDeviceConfig(ctx context.Context, deviceID string, req *UpdateDeviceConfigRequest) error {
- var device Device
- // 查询设备
- if err := m.db.WithContext(ctx).Where("id = ?", deviceID).First(&device).Error; err != nil {
- if err == gorm.ErrRecordNotFound {
- return fmt.Errorf("device not found")
- }
- m.logger.Error("Failed to get device", zap.Error(err))
- return fmt.Errorf("failed to get device: %w", err)
- }
- // 更新配置
- device.Config = req.Config
- // 保存更新
- if err := m.db.WithContext(ctx).Save(&device).Error; err != nil {
- m.logger.Error("Failed to update device config", zap.Error(err))
- return fmt.Errorf("failed to update device config: %w", err)
- }
- // 创建配置更新事件
- event := &DeviceEvent{
- ID: generateEventID(),
- DeviceID: deviceID,
- Type: EventConfig,
- Severity: SeverityInfo,
- Message: "设备配置已更新",
- Timestamp: time.Now(),
- }
- if err := m.db.WithContext(ctx).Create(event).Error; err != nil {
- m.logger.Error("Failed to create device event", zap.Error(err))
- }
- m.logger.Info("Device config updated", zap.String("device_id", deviceID))
- return nil
- }
- // UpdateFirmware 更新设备固件
- func (m *Manager) UpdateFirmware(ctx context.Context, deviceID string, req *UpdateFirmwareRequest) error {
- var device Device
- // 查询设备
- if err := m.db.WithContext(ctx).Where("id = ?", deviceID).First(&device).Error; err != nil {
- if err == gorm.ErrRecordNotFound {
- return fmt.Errorf("device not found")
- }
- m.logger.Error("Failed to get device", zap.Error(err))
- return fmt.Errorf("failed to get device: %w", err)
- }
- // 更新固件信息
- device.Firmware = FirmwareInfo{
- Version: req.Version,
- URL: req.URL,
- Description: req.Description,
- ReleaseDate: time.Now(),
- }
- // 更新设备状态为更新中
- device.Status = StatusUpdating
- // 保存更新
- if err := m.db.WithContext(ctx).Save(&device).Error; err != nil {
- m.logger.Error("Failed to update device firmware", zap.Error(err))
- return fmt.Errorf("failed to update device firmware: %w", err)
- }
- // 创建固件更新事件
- event := &DeviceEvent{
- ID: generateEventID(),
- DeviceID: deviceID,
- Type: EventFirmware,
- Severity: SeverityInfo,
- Message: fmt.Sprintf("固件更新开始,版本: %s", req.Version),
- Timestamp: time.Now(),
- }
- if err := m.db.WithContext(ctx).Create(event).Error; err != nil {
- m.logger.Error("Failed to create device event", zap.Error(err))
- }
- m.logger.Info("Device firmware update started",
- zap.String("device_id", deviceID),
- zap.String("version", req.Version))
- // TODO: 实际的固件更新逻辑
- // 这里应该通过协议适配器发送固件更新命令
- return nil
- }
- // StartStatusCheck 启动设备状态检查
- func (m *Manager) StartStatusCheck() {
- ticker := time.NewTicker(5 * time.Minute)
- defer ticker.Stop()
- for {
- select {
- case <-ticker.C:
- m.checkDeviceStatus()
- }
- }
- }
- // checkDeviceStatus 检查设备状态
- func (m *Manager) checkDeviceStatus() {
- ctx := context.Background()
- var devices []Device
- // 查询所有在线设备
- if err := m.db.WithContext(ctx).Where("status = ?", StatusOnline).Find(&devices).Error; err != nil {
- m.logger.Error("Failed to get online devices", zap.Error(err))
- return
- }
- // 检查每个设备的最后在线时间
- now := time.Now()
- for _, device := range devices {
- if device.LastSeen != nil && now.Sub(*device.LastSeen) > 10*time.Minute {
- // 设备离线
- device.Status = StatusOffline
- m.db.WithContext(ctx).Save(&device)
- // 创建离线事件
- event := &DeviceEvent{
- ID: generateEventID(),
- DeviceID: device.ID,
- Type: EventDisconnect,
- Severity: SeverityWarning,
- Message: "设备离线",
- Timestamp: now,
- }
- m.db.WithContext(ctx).Create(event)
- m.logger.Info("Device went offline", zap.String("device_id", device.ID))
- }
- }
- }
- // generateDeviceID 生成设备ID
- func generateDeviceID(deviceType string) string {
- return fmt.Sprintf("%s_%d", deviceType, time.Now().UnixNano())
- }
- // generateEventID 生成事件ID
- func generateEventID() string {
- return fmt.Sprintf("event_%d", time.Now().UnixNano())
- }
|