package service import ( "bytes" "city_chips/internal/model" "city_chips/internal/repository" "context" "encoding/json" "errors" "fmt" "github.com/spf13/viper" "io" "net/http" "net/url" "reflect" "strings" ) type IlluminatingService interface { GetIlluminating(ctx context.Context, id int64) (*model.Illuminating, error) Illuminating(method, url string, body any) ([]byte, error) GetStatistics() ([]byte, error) GetBaseecic(currentPage, device_type_id, devices_enabled, gateway_id, pageSize int, query, devices_udid string) (model.IlluminatingBaseecic, error) GetAlarm(currentPage, pageSize int) ([]byte, error) GetAlarmStatistics(start_time, end_time string) ([]byte, error) GetgatewayFind() (model.GatewayFind, error) DevicesControl(agreement_json, request_id, udid string, source int) (model.DevicesControl, error) GetDeviceOrgid(currentPage, pageSize, searchText string) ([]byte, error) } func NewIlluminatingService( service *Service, illuminatingRepository repository.IlluminatingRepository, viperViper *viper.Viper, client *http.Client, ) IlluminatingService { if client == nil { client = http.DefaultClient } return &illuminatingService{ Service: service, illuminatingRepository: illuminatingRepository, conf: viperViper, client: client, } } type illuminatingService struct { *Service illuminatingRepository repository.IlluminatingRepository conf *viper.Viper client *http.Client } func (s *illuminatingService) GetIlluminating(ctx context.Context, id int64) (*model.Illuminating, error) { return s.illuminatingRepository.GetIlluminating(ctx, id) } func (s *illuminatingService) Illuminating(method, url string, body any) ([]byte, error) { login, err := s.login() if err != nil { return nil, err } var reqBody io.Reader var finalURL = url // 如果是 GET 请求,把 body 当作 query 参数处理 if method == http.MethodGet || method == "" { vals, err := buildQueryParams(body) if err != nil { return nil, err } finalURL = addQueryParams(url, vals) } else { // 非 GET 请求才构造 body reqBody, err = buildRequestBody(body) if err != nil { return nil, err } } request, err := http.NewRequest(method, finalURL, reqBody) if err != nil { return nil, err } request.Header.Set("Authorization", login.AccessToken) response, err := s.client.Do(request) if err != nil { return nil, err } defer response.Body.Close() respBody, err := io.ReadAll(response.Body) if err != nil { return nil, err } return respBody, nil } // login 封装登录逻辑 func (s *illuminatingService) login() (*model.Login, error) { auth := s.conf.GetString("illuminating.authorization") clientId := s.conf.GetInt("illuminating.clientId") mobile := s.conf.GetString("illuminating.mobile") password := s.conf.GetString("illuminating.password") loginReq := model.LoginRequst{ Authorization: auth, ClientId: clientId, Mobile: mobile, Password: password, } bodyBytes, err := json.Marshal(loginReq) if err != nil { return nil, err } url := s.conf.GetString("illuminating.baseUrl") + s.conf.GetString("illuminating.api.login") request, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) if err != nil { return nil, err } response, err := s.client.Do(request) if err != nil { return nil, err } defer response.Body.Close() respBody, err := io.ReadAll(response.Body) if err != nil { return nil, err } var login model.Login if err := json.Unmarshal(respBody, &login); err != nil { return nil, err } return &login, nil } // 构建请求体工具函数 func buildRequestBody(body any) (io.Reader, error) { if body == nil { return nil, nil } bodyBytes, err := json.Marshal(body) if err != nil { return nil, err } return bytes.NewBuffer(bodyBytes), nil } func buildQueryParams(params any) (url.Values, error) { vals := make(url.Values) switch p := params.(type) { case nil: return vals, nil case url.Values: return p, nil case map[string]string: for k, v := range p { vals.Add(k, v) } case map[string][]string: for k, v := range p { for _, vv := range v { vals.Add(k, vv) } } default: // 使用反射解析结构体字段 t := reflect.TypeOf(p) v := reflect.ValueOf(p) for i := 0; i < t.NumField(); i++ { field := t.Field(i) value := v.Field(i).Interface() tag := field.Tag.Get("json") if tag == "" { tag = field.Name } vals.Add(tag, fmt.Sprintf("%v", value)) } } return vals, nil } func addQueryParams(baseURL string, values url.Values) string { if len(values) == 0 { return baseURL } u, err := url.Parse(baseURL) if err != nil { return baseURL // 忽略错误直接返回原值 } q := u.Query() for k, vs := range values { for _, v := range vs { q.Add(k, v) } } u.RawQuery = q.Encode() return u.String() } // GetStatistics 获取统计信息 func (s *illuminatingService) GetStatistics() ([]byte, error) { urls := s.conf.GetString("illuminating.baseUrl") + s.conf.GetString("illuminating.api.statistics") illuminating, err := s.Illuminating("GET", urls, nil) if err != nil { return nil, errors.New("获取统计信息失败") } return illuminating, nil } // GetDeviceStatistics 获取设备统计信息 func (s *illuminatingService) GetDeviceStatistics() ([]byte, error) { urls := s.conf.GetString("illuminating.baseUrl") + s.conf.GetString("illuminating.api.deviceStatistics") illuminating, err := s.Illuminating("GET", urls, nil) if err != nil { return nil, errors.New("获取设备统计信息失败") } return illuminating, nil } // GetAlarm 获取报警信息 func (s *illuminatingService) GetAlarm(currentPage, pageSize int) ([]byte, error) { urls := s.conf.GetString("illuminating.baseUrl") + s.conf.GetString("illuminating.api.alarm") m := make(map[string]any) m["currentPage"] = currentPage m["pageSize"] = pageSize illuminating, err := s.Illuminating("POST", urls, m) if err != nil { return nil, errors.New("获取统计信息失败") } return illuminating, nil } // GetAlarmStatistics 获取报警统计信息 func (s *illuminatingService) GetAlarmStatistics(start_time, end_time string) ([]byte, error) { urls := s.conf.GetString("illuminating.baseUrl") + s.conf.GetString("illuminating.api.alarmStatistics") urls += "?start_time=" + start_time + "&end_time=" + end_time illuminating, err := s.Illuminating("GET", urls, nil) if err != nil { return nil, errors.New("获取统计信息失败") } return illuminating, nil } // GetBaseecic 获取照明监控列表 func (s *illuminatingService) GetBaseecic(currentPage, device_type_id, devices_enabled, gateway_id, pageSize int, query, devices_udid string) (model.IlluminatingBaseecic, error) { var baseecic model.IlluminatingBaseecic urls := s.conf.GetString("illuminating.baseUrl") + s.conf.GetString("illuminating.api.baseecic") m := make(map[string]any) m["currentPage"] = currentPage m["pageSize"] = pageSize if currentPage == 0 { m["currentPage"] = 1 } if pageSize == 0 { m["pageSize"] = 20 } if device_type_id != 0 { m["device_type_id"] = device_type_id } if devices_enabled != 0 { m["devices_enabled"] = devices_enabled } if gateway_id != 0 { m["gateway_id"] = gateway_id } if devices_udid != "" { m["devices_udid"] = devices_udid } if query != "" { m["query"] = query } illuminating, err := s.Illuminating("POST", urls, m) if err != nil { return model.IlluminatingBaseecic{}, errors.New("获取统计信息失败") } err = json.Unmarshal(illuminating, &baseecic) if err != nil { return model.IlluminatingBaseecic{}, errors.New("json反序列化失败") } return baseecic, nil } // GetgatewayFind 获取网关列表 func (s *illuminatingService) GetgatewayFind() (model.GatewayFind, error) { var gateway model.GatewayFind urls := s.conf.GetString("illuminating.baseUrl") + s.conf.GetString("illuminating.api.gatewayFind") m := make(map[string]any) m["gateway_type"] = -1 illuminating, err := s.Illuminating("POST", urls, m) if err != nil { return model.GatewayFind{}, errors.New("获取统计信息失败") } err = json.Unmarshal(illuminating, &gateway) if err != nil { return model.GatewayFind{}, errors.New("json反序列化失败") } return gateway, nil } // DevicesControl 设备控制 func (s *illuminatingService) DevicesControl(agreement_json, request_id, udid string, source int) (model.DevicesControl, error) { var devicesControl model.DevicesControl urls := s.conf.GetString("illuminating.baseUrl") + s.conf.GetString("illuminating.api.devicesControl") m := make(map[string]any) m["agreement_json"] = agreement_json if request_id != "" { m["request_id"] = request_id } m["source"] = source m["udid"] = udid illuminating, err := s.Illuminating("POST", urls, m) if err != nil { return model.DevicesControl{}, errors.New("控制灯光设备失败") } err = json.Unmarshal(illuminating, &devicesControl) if err != nil { return model.DevicesControl{}, errors.New("json反序列化失败") } return devicesControl, nil } // GetDeviceOrgid 获取定时策略 func (s *illuminatingService) GetDeviceOrgid(currentPage, pageSize, searchText string) ([]byte, error) { searchText = strings.ReplaceAll(searchText, " ", "") urls := s.conf.GetString("illuminating.baseUrl") + s.conf.GetString("illuminating.api.deviceOrgid") urls += "?currentPage=" + currentPage + "&pageSize=" + pageSize + "&searchText=" + searchText illuminating, err := s.Illuminating("GET", urls, nil) if err != nil { return nil, errors.New("获取统计信息失败") } return illuminating, nil }