package service import ( "city_chips/internal/model" "city_chips/internal/repository" "city_chips/pkg/helper/obix" "context" "fmt" "github.com/pkg/errors" "github.com/spf13/viper" "go.uber.org/zap" "regexp" "sync" ) type IntelligentBuildingControlService interface { GetIntelligentBuildingControl(ctx context.Context, id int64) (*model.IntelligentBuildingControl, error) GetPoint(conds map[string]any, pageNum, pageSize int) (*[]model.Point, int64, error) GetPointType() ([]string, error) DeviceType() ([]string, error) DeviceCount() (int64, error) GetDevices(conds map[string]any, pageNum, pageSize int) (map[string]any, int64, error) } func NewIntelligentBuildingControlService( service *Service, intelligentBuildingControlRepository repository.IntelligentBuildingControlRepository, conf *viper.Viper, ) IntelligentBuildingControlService { return &intelligentBuildingControlService{ Service: service, intelligentBuildingControlRepository: intelligentBuildingControlRepository, conf: conf, } } type intelligentBuildingControlService struct { *Service intelligentBuildingControlRepository repository.IntelligentBuildingControlRepository conf *viper.Viper } // DeviceCount 获取设备总数 func (s *intelligentBuildingControlService) DeviceCount() (int64, error) { //TODO implement me count, err := s.intelligentBuildingControlRepository.DeviceCount() if err != nil { return 0, err } return count, nil } // DeviceType 获取设备类型 func (s *intelligentBuildingControlService) DeviceType() ([]string, error) { //TODO implement me poions, err := s.intelligentBuildingControlRepository.DeviceType() if err != nil { return nil, err } return poions, nil } // GetPointType 获取点位类型 func (s *intelligentBuildingControlService) GetPointType() ([]string, error) { poions, err := s.intelligentBuildingControlRepository.GetPointType() if err != nil { return nil, err } return poions, nil } // GetPoint 获取点位列表 func (s *intelligentBuildingControlService) GetPoint(conds map[string]any, pageNum, pageSize int) (*[]model.Point, int64, error) { points, total, err := s.intelligentBuildingControlRepository.GetPoint(conds, pageNum, pageSize) if err != nil { return &[]model.Point{}, 0, err } return points, total, err } func (s *intelligentBuildingControlService) GetIntelligentBuildingControl(ctx context.Context, id int64) (*model.IntelligentBuildingControl, error) { return s.intelligentBuildingControlRepository.GetIntelligentBuildingControl(ctx, id) } // GetDevices 获取设备列表(支持设备 & 点位双重并发) func (s *intelligentBuildingControlService) GetDevices(conds map[string]any, pageNum, pageSize int) (map[string]any, int64, error) { var total int64 baseUrl := s.conf.GetString("obix.baseUrl") device := make(map[string]any) list, total, err := s.intelligentBuildingControlRepository.GetPopintList(conds, pageNum, pageSize) if err != nil { return nil, 0, errors.New("获取设备列表失败") } var wg sync.WaitGroup var mu sync.Mutex // 保护 device 的写入 var all *[]model.Point for _, v := range list { wg.Add(1) go func(deviceName string) { defer wg.Done() all, err = s.intelligentBuildingControlRepository.GetPointAll(map[string]any{"device_name": deviceName}) if err != nil { s.logger.Error("获取设备点位列表失败", zap.String("device", deviceName), zap.Error(err)) return } m := make(map[string]any) var innerWg sync.WaitGroup var innerMu sync.Mutex // 保护 m 的写入 for _, vl := range *all { innerWg.Add(1) go func(vl model.Point) { defer innerWg.Done() url := baseUrl + vl.FullPath request, err := obix.SendSecureRequest(url, s.conf.GetString("obix.username"), s.conf.GetString("obix.password")) if err != nil { s.logger.Error("发送请求失败", zap.String("url", url), zap.Error(err)) return } re := regexp.MustCompile(`val="([^"]+)"`) matches := re.FindStringSubmatch(request) if len(matches) > 1 { key := model.PointName[vl.PointName] if key != "" { value := matches[1] switch val := obix.DetectType(value).(type) { case int: innerMu.Lock() m[key] = val innerMu.Unlock() case float64: innerMu.Lock() m[key] = fmt.Sprintf("%.2f", val) innerMu.Unlock() case bool: innerMu.Lock() if val { m[key] = "是" } else { m[key] = "否" } innerMu.Unlock() default: innerMu.Lock() m[key] = value innerMu.Unlock() } } } else { s.logger.Warn("未找到 val 值", zap.String("url", url)) } }(vl) } innerWg.Wait() mu.Lock() device[deviceName] = m mu.Unlock() }(v) } wg.Wait() return device, total, nil }