package handler import ( "city_chips/internal/model" "city_chips/internal/service" "city_chips/pkg/helper/obix" "city_chips/pkg/helper/resp" "encoding/json" "fmt" "go.uber.org/zap" "math/rand" "regexp" "sync" "time" "github.com/spf13/viper" "github.com/gin-gonic/gin" ) type IntelligentBuildingControlHandler struct { *Handler intelligentBuildingControlService service.IntelligentBuildingControlService conf *viper.Viper } func NewIntelligentBuildingControlHandler( handler *Handler, intelligentBuildingControlService service.IntelligentBuildingControlService, conf *viper.Viper, ) *IntelligentBuildingControlHandler { return &IntelligentBuildingControlHandler{ Handler: handler, intelligentBuildingControlService: intelligentBuildingControlService, conf: conf, } } // 智能楼宇控制系统 // 示例:创建一个报警记录 func generateAlarm() model.AlarmList { return model.AlarmList{ Id: rand.Intn(100), Name: model.GetRandomItem(model.DeviceNames), State: rand.Intn(2), // 假设0为正常,1为报警 Date: time.Now().Format("2006-01-02 15:04:05"), Location: model.GetRandomItem(model.Locations), AlarmContent: model.GetRandomItem(model.AlarmContents), } } func (h *IntelligentBuildingControlHandler) GetIntelligentBuildingControl(ctx *gin.Context) { m := make(map[string]any) var device []model.AlarmList for i := 0; i < 20; i++ { alarm := generateAlarm() device = append(device, alarm) } count, err := h.intelligentBuildingControlService.DeviceCount() if err != nil { resp.HandleError(ctx, 1201, "查询设备总数失败", nil) return } m["DeviceCount"] = count //设备总数 m["StopState"] = rand.Intn(100) //停止状态 m["RunState"] = rand.Intn(100) //运行状态 m["FaultState"] = rand.Intn(1000) //故障状态 m["DeviceList"] = device //设备列表 resp.HandleSuccess(ctx, m) } func (h *IntelligentBuildingControlHandler) GetPoint(ctx *gin.Context) { pointName := ctx.PostForm("pointName") deviceType := ctx.PostForm("deviceType") building := ctx.PostForm("building") floor := ctx.PostForm("floor") section := ctx.PostForm("section") device_name := ctx.PostForm("deviceName") conds := make(map[string]any) var pointType []model.PointType if pointName != "" { conds["point_name"] = pointName } if deviceType != "" { conds["device_type"] = deviceType } if building != "" { conds["building"] = building } if floor != "" { conds["floor"] = floor } if section != "" { conds["section"] = section } if device_name != "" { conds["device_name"] = device_name } baseUrl := h.conf.GetString("obix.baseUrl") points, err := h.intelligentBuildingControlService.GetPoint(conds) if err != nil { resp.HandleError(ctx, 1201, "查询点位失败", nil) return } var wg sync.WaitGroup var mutex sync.Mutex // 保护切片并发写入 m := make(map[string]string) sem := make(chan struct{}, 10) // 最大并发数为10 for _, v := range *points { url := baseUrl + v.FullPath wg.Add(1) sem <- struct{}{} go func(url string, pointName string) { defer func() { <-sem wg.Done() }() request, err := obix.SendSecureRequest(url, h.conf.GetString("obix.username"), h.conf.GetString("obix.password")) if err != nil { h.logger.Error("发送请求失败", zap.Error(err)) return } re := regexp.MustCompile(`val="([^"]+)"`) matches := re.FindStringSubmatch(request) mutex.Lock() defer mutex.Unlock() if len(matches) > 1 { s := model.PointName[pointName] m[s] = matches[1] pointType = append(pointType, model.PointType{Type: m}) } else { h.logger.Warn("未找到 val 值", zap.String("url", url)) } }(url, v.PointName) } // 等待所有协程完成 wg.Wait() // 统一返回结果 resp.HandleSuccess(ctx, pointType) } func (h *IntelligentBuildingControlHandler) GetGetPointSSE(ctx *gin.Context) { // 设置响应头 ctx.Header("Content-Type", "text/event-stream") ctx.Header("Cache-Control", "no-cache") ctx.Header("Connection", "keep-alive") // 监听客户端断开连接 conn := true notify := ctx.Writer.CloseNotify() type Response struct { RequestId string `protobuf:"bytes,1,opt,name=requestId,proto3" json:"requestId,omitempty"` Code int32 `protobuf:"varint,2,opt,name=code,proto3" json:"code,omitempty"` Msg string `protobuf:"bytes,3,opt,name=msg,proto3" json:"msg,omitempty"` Data any `json:"data"` } pointName := ctx.Query("pointName") deviceType := ctx.Query("deviceType") building := ctx.Query("building") floor := ctx.Query("floor") section := ctx.Query("section") device_name := ctx.Query("deviceName") conds := make(map[string]any) if pointName != "" { conds["point_name"] = pointName } if deviceType != "" { conds["device_type"] = deviceType } if building != "" { conds["building"] = building } if floor != "" { conds["floor"] = floor } if section != "" { conds["section"] = section } if device_name != "" { conds["device_name"] = device_name } baseUrl := h.conf.GetString("obix.baseUrl") var response Response for conn { select { case <-notify: conn = false fmt.Println("断开连接") return default: m := make(map[string]any) points, err := h.intelligentBuildingControlService.GetPoint(conds) if err != nil { resp.HandleError(ctx, 1201, "查询点位失败", nil) conn = false } for _, v := range *points { url := baseUrl + v.FullPath request, err := obix.SendSecureRequest(url, h.conf.GetString("obix.username"), h.conf.GetString("obix.password")) if err != nil { h.logger.Error("发送请求失败", zap.Error(err)) conn = false return } re := regexp.MustCompile(`val="([^"]+)"`) matches := re.FindStringSubmatch(request) if len(matches) > 1 { s := model.PointName[v.PointName] if s != "" { value := matches[1] switch val := obix.DetectType(value).(type) { case int: m[s] = val case float64: m[s] = fmt.Sprintf("%.2f", val) // 保留两位小数输出 case bool: if val { m[s] = "是" } else { m[s] = "否" } default: m[s] = value // 原样输出字符串 } } } else { h.logger.Warn("未找到 val 值", zap.String("url", url)) conn = false } } response.Code = 200 response.RequestId = ctx.ClientIP() response.Msg = "success" response.Data = m res, _ := json.Marshal(&response) fmt.Fprintf(ctx.Writer, "data: %s\n\n", string(res)) ctx.Writer.Flush() time.Sleep(10 * time.Second) } } } // GetPointType 获取点位类型 func (h *IntelligentBuildingControlHandler) GetPointType(ctx *gin.Context) { var tempS1 model.NumericPoint // var xmlData = ` // // // // // //` //err2 := ctx.ShouldBindXML(&tempS1) //err2 := xml.Unmarshal([]byte(xmlData), &tempS1) //if err2 != nil { // resp.HandleError(ctx, 1201, "绑定XML失败", nil) // return //} request, err2 := obix.SendSecureRequest("https://10.1.201.253/obix/config/Drivers/BacnetNetwork/DDC_9B_1F_1a/points/PAU/PAU_9B_1F_1/PAUAlr1", h.conf.GetString("obix.username"), h.conf.GetString("obix.password")) if err2 != nil { resp.HandleError(ctx, 1201, "发送请求失败", nil) return } fmt.Println(request, "===========") fmt.Println(tempS1) points, err := h.intelligentBuildingControlService.GetPointType() if err != nil { resp.HandleError(ctx, 1201, "查询点位类型失败", nil) return } resp.HandleSuccess(ctx, points) } func (h *IntelligentBuildingControlHandler) GetDeviceType(ctx *gin.Context) { points, err := h.intelligentBuildingControlService.DeviceType() if err != nil { resp.HandleError(ctx, 1201, "查询设备类型失败", nil) return } m := make(map[string]string) for _, v := range points { m[v] = model.DeviceType[v] } resp.HandleSuccess(ctx, m) }