package lc import ( "encoding/xml" "github.com/sirupsen/logrus" "io" "io/ioutil" "lc-smartX/lc/model" "lc-smartX/util" "lc-smartX/util/gopool" "log" "mime/multipart" "net/http" "strings" "time" ) func NewCameraEventServer() *CameraServer { server := &CameraServer{Cameras: util.Config.Cameras, Notifiers: make(map[string]Notifier, 4)} return server } type CameraServer struct { Cameras []model.CameraInfo Notifiers map[string]Notifier } func (s *CameraServer) Start() { http.HandleFunc(util.Config.HikServer.Path, s.Handler) logrus.Fatal("事件监听服务启动失败:", util.Config.HikServer.Addr, ", error:", http.ListenAndServe(util.Config.HikServer.Addr, nil)) } func (s *CameraServer) RegisterCallback(branch byte, notifier Notifier) { for _, camera := range s.Cameras { s.Notifiers[camera.IP] = notifier } } func (s *CameraServer) Callback(ip string) { notifier, ok := s.Notifiers[ip] if !ok { logrus.Errorf("回调函数注册表没有该ip:%s", ip) return } notifier.Notify() logrus.Debugf("camera [%s] Callback", ip) } func (s *CameraServer) Handler(w http.ResponseWriter, r *http.Request) { gopool.Go(func() { //监听主机应答固定,直接先应答 w.WriteHeader(200) w.Header().Add("Date", time.Now().String()) w.Header().Add("Connection", "keep-alive") }) //1. contentType := r.Header.Get("Content-Type") if strings.Contains(contentType, "application/xml") { bytes, err := io.ReadAll(r.Body) if err != nil { return } var event model.EventNotificationAlert err = xml.Unmarshal(bytes, &event) if err != nil { return } logrus.Errorf("EventNotificationAlert = %+v", event) //发送事件通知 s.Callback(event.IpAddress) } else if strings.Contains(contentType, "multipart/form-data") { s.HandleMultipart(r) } } // 处理多文件事件 func (s *CameraServer) HandleMultipart(r *http.Request) { multipartReader := multipart.NewReader(r.Body, "boundary") // 循环读取每个 part var event model.EventNotificationAlert for { part, err := multipartReader.NextPart() //defer part.Close() if err == io.EOF { break } if err != nil { log.Println("Failed to read part:", err) return } if part.FormName() != "linedetectionImage" || !strings.Contains(part.FormName(), "Image") { //不含图片的xml部分数据 xmlData, err := ioutil.ReadAll(part) if err != nil { return } xml.Unmarshal(xmlData, &event) continue } } //发送事件通知 s.Callback(event.IpAddress) }