package isapi import ( "encoding/xml" "fmt" mail "github.com/xhit/go-simple-mail/v2" "io" "io/ioutil" "log" "mime/multipart" "net/http" "strings" "time" ) type Server struct { } func (s *Server) Start() { http.HandleFunc("/event", handler) log.Fatal("事件监听服务启动失败", http.ListenAndServe(":8850", nil)) } func (s *Server) Stop() { } func handler(w http.ResponseWriter, r *http.Request) { go func() { //监听主机应答固定,直接先应答 w.WriteHeader(200) w.Header().Add("Date", time.Now().String()) w.Header().Add("Connection", "close") }() //logRequest(r) contentType := r.Header.Get("Content-Type") if strings.Contains(contentType, "application/xml") { bytes, err := ioutil.ReadAll(r.Body) if err != nil { return } var event EventNotificationAlert err = xml.Unmarshal(bytes, &event) if err != nil { return } //处理事件 todo 邮箱 handleEvent_(event) } else if strings.Contains(contentType, "multipart/form-data") { //fmt.Println("multipart/form-data 事件") handleMultipart(r) } else { return } } //TODO 限制事件重复触发,一段时间内不重复发送邮件,但保持报警状态 // 处理多文件事件 func handleMultipart(r *http.Request) { // todo 远程联动-ip音柱 multipartReader := multipart.NewReader(r.Body, "boundary") var msg string //邮件消息 // 循环读取每个 part var eventAlert EventNotificationAlert for { part, err := multipartReader.NextPart() //defer part.Close() if err == io.EOF { break } if err != nil { log.Println("Failed to read part:", err) continue } // 检查 part 的 Content-Disposition formName := part.FormName() fmt.Println("formName", formName) if formName != "intrusionImage" { //不含图片的xml部分数据 xmlData, err := ioutil.ReadAll(part) if err != nil { return } xml.Unmarshal(xmlData, &eventAlert) //event.Ip = eventAlert.IpAddress //event.Type = eventAlert.EventType //event.StartTime = eventAlert.DateTime msg = handleEvent_(eventAlert) continue } fmt.Printf("eventAlert:%+v\n", eventAlert) //处理图片部分数据 contentType := part.Header.Get("Content-Type") //eventCode := part.Header.Get("Content-ID") picName := timeFmt(eventAlert.DateTime) + ".jpeg" //event.Name = picName data, _ := ioutil.ReadAll(part) f := &mail.File{ Name: picName, MimeType: contentType, Data: data, Inline: true, } //邮件通知 SendAlarmEmail(eventAlert.MacAddress, msg, f) } } func handleEvent_(event EventNotificationAlert) string { var eType string if event.EventType == "duration" { eType = event.DurationList.Duration[0].RelationEvent } else { eType = event.EventType } return fmt.Sprintf("事件类型:%s,时间:%s", sMap[eType], timeFmt(event.DateTime)) } func timeFmt(str string) string { s := strings.Split(str, "T") t := s[0] s1 := strings.Split(s[1], ".") s2 := strings.Split(s1[0], "+") return t + " " + s2[0] } func logRequest(req *http.Request) { // 打印请求行 fmt.Printf("%s %s %s\n", req.Method, req.URL.Path, req.Proto) // 打印请求头 for name, headers := range req.Header { for _, h := range headers { fmt.Printf("%v: %v\n", name, h) } } // 打印请求体 body, _ := ioutil.ReadAll(req.Body) fmt.Printf("%s\n", body) } type EventNotificationAlert struct { IpAddress string `xml:"ipAddress"` PortNo string `xml:"portNo"` Protocol string `xml:"protocol"` MacAddress string `xml:"macAddress"` ChannelID string `xml:"channelID"` DateTime string `xml:"dateTime"` ActivePostCount string `xml:"activePostCount"` EventType string `xml:"eventType"` EventState string `xml:"eventState"` EventDescription string `xml:"eventDescription"` DetectionRegionList struct { DetectionRegionEntry []struct { RegionID string `xml:"regionID"` SensitivityLevel string `xml:"sensitivityLevel"` RegionCoordinatesList struct { RegionCoordinates []struct { PositionX string `xml:"positionX"` PositionY string `xml:"positionY"` } `xml:"RegionCoordinates"` } `xml:"RegionCoordinatesList"` DetectionTarget string `xml:"detectionTarget"` TargetRect struct { X string `xml:"X"` Y string `xml:"Y"` Width string `xml:"width"` Height string `xml:"height"` } `xml:"TargetRect"` } `xml:"DetectionRegionEntry"` } `xml:"DetectionRegionList"` ChannelName string `xml:"channelName"` DetectionPictureTransType string `xml:"detectionPictureTransType"` DetectionPicturesNumber string `xml:"detectionPicturesNumber"` IsDataRetransmission string `xml:"isDataRetransmission"` DurationList struct { Duration []struct { RelationEvent string `xml:"relationEvent"` } `xml:"Duration"` } `xml:"DurationList"` } var sMap = map[string]string{ "shelteralarm": "遮盖报警", "regionEntrance": "进入区域", "fielddetection": "区域入侵", "linedetection": "越界侦测", }