server.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. package isapi
  2. import (
  3. "encoding/xml"
  4. "fmt"
  5. mail "github.com/xhit/go-simple-mail/v2"
  6. "io"
  7. "io/ioutil"
  8. "log"
  9. "mime/multipart"
  10. "net/http"
  11. "strings"
  12. "time"
  13. )
  14. type Server struct {
  15. }
  16. func (s *Server) Start() {
  17. http.HandleFunc("/event", handler)
  18. log.Fatal("事件监听服务启动失败", http.ListenAndServe(":8850", nil))
  19. }
  20. func (s *Server) Stop() {
  21. }
  22. func handler(w http.ResponseWriter, r *http.Request) {
  23. go func() {
  24. //监听主机应答固定,直接先应答
  25. w.WriteHeader(200)
  26. w.Header().Add("Date", time.Now().String())
  27. w.Header().Add("Connection", "close")
  28. }()
  29. //logRequest(r)
  30. contentType := r.Header.Get("Content-Type")
  31. if strings.Contains(contentType, "application/xml") {
  32. bytes, err := ioutil.ReadAll(r.Body)
  33. if err != nil {
  34. return
  35. }
  36. var event EventNotificationAlert
  37. err = xml.Unmarshal(bytes, &event)
  38. if err != nil {
  39. return
  40. }
  41. //处理事件 todo 邮箱
  42. handleEvent_(event)
  43. } else if strings.Contains(contentType, "multipart/form-data") {
  44. //fmt.Println("multipart/form-data 事件")
  45. handleMultipart(r)
  46. } else {
  47. return
  48. }
  49. }
  50. //TODO 限制事件重复触发,一段时间内不重复发送邮件,但保持报警状态
  51. // 处理多文件事件
  52. func handleMultipart(r *http.Request) {
  53. // todo 远程联动-ip音柱
  54. multipartReader := multipart.NewReader(r.Body, "boundary")
  55. var msg string //邮件消息
  56. // 循环读取每个 part
  57. var eventAlert EventNotificationAlert
  58. for {
  59. part, err := multipartReader.NextPart()
  60. //defer part.Close()
  61. if err == io.EOF {
  62. break
  63. }
  64. if err != nil {
  65. log.Println("Failed to read part:", err)
  66. continue
  67. }
  68. // 检查 part 的 Content-Disposition
  69. formName := part.FormName()
  70. fmt.Println("formName", formName)
  71. if formName != "intrusionImage" {
  72. //不含图片的xml部分数据
  73. xmlData, err := ioutil.ReadAll(part)
  74. if err != nil {
  75. return
  76. }
  77. xml.Unmarshal(xmlData, &eventAlert)
  78. //event.Ip = eventAlert.IpAddress
  79. //event.Type = eventAlert.EventType
  80. //event.StartTime = eventAlert.DateTime
  81. msg = handleEvent_(eventAlert)
  82. continue
  83. }
  84. fmt.Printf("eventAlert:%+v\n", eventAlert)
  85. //处理图片部分数据
  86. contentType := part.Header.Get("Content-Type")
  87. //eventCode := part.Header.Get("Content-ID")
  88. picName := timeFmt(eventAlert.DateTime) + ".jpeg"
  89. //event.Name = picName
  90. data, _ := ioutil.ReadAll(part)
  91. f := &mail.File{
  92. Name: picName,
  93. MimeType: contentType,
  94. Data: data,
  95. Inline: true,
  96. }
  97. //邮件通知
  98. SendAlarmEmail(eventAlert.MacAddress, msg, f)
  99. }
  100. }
  101. func handleEvent_(event EventNotificationAlert) string {
  102. var eType string
  103. if event.EventType == "duration" {
  104. eType = event.DurationList.Duration[0].RelationEvent
  105. } else {
  106. eType = event.EventType
  107. }
  108. return fmt.Sprintf("事件类型:%s,时间:%s", sMap[eType], timeFmt(event.DateTime))
  109. }
  110. func timeFmt(str string) string {
  111. s := strings.Split(str, "T")
  112. t := s[0]
  113. s1 := strings.Split(s[1], ".")
  114. s2 := strings.Split(s1[0], "+")
  115. return t + " " + s2[0]
  116. }
  117. func logRequest(req *http.Request) {
  118. // 打印请求行
  119. fmt.Printf("%s %s %s\n", req.Method, req.URL.Path, req.Proto)
  120. // 打印请求头
  121. for name, headers := range req.Header {
  122. for _, h := range headers {
  123. fmt.Printf("%v: %v\n", name, h)
  124. }
  125. }
  126. // 打印请求体
  127. body, _ := ioutil.ReadAll(req.Body)
  128. fmt.Printf("%s\n", body)
  129. }
  130. type EventNotificationAlert struct {
  131. IpAddress string `xml:"ipAddress"`
  132. PortNo string `xml:"portNo"`
  133. Protocol string `xml:"protocol"`
  134. MacAddress string `xml:"macAddress"`
  135. ChannelID string `xml:"channelID"`
  136. DateTime string `xml:"dateTime"`
  137. ActivePostCount string `xml:"activePostCount"`
  138. EventType string `xml:"eventType"`
  139. EventState string `xml:"eventState"`
  140. EventDescription string `xml:"eventDescription"`
  141. DetectionRegionList struct {
  142. DetectionRegionEntry []struct {
  143. RegionID string `xml:"regionID"`
  144. SensitivityLevel string `xml:"sensitivityLevel"`
  145. RegionCoordinatesList struct {
  146. RegionCoordinates []struct {
  147. PositionX string `xml:"positionX"`
  148. PositionY string `xml:"positionY"`
  149. } `xml:"RegionCoordinates"`
  150. } `xml:"RegionCoordinatesList"`
  151. DetectionTarget string `xml:"detectionTarget"`
  152. TargetRect struct {
  153. X string `xml:"X"`
  154. Y string `xml:"Y"`
  155. Width string `xml:"width"`
  156. Height string `xml:"height"`
  157. } `xml:"TargetRect"`
  158. } `xml:"DetectionRegionEntry"`
  159. } `xml:"DetectionRegionList"`
  160. ChannelName string `xml:"channelName"`
  161. DetectionPictureTransType string `xml:"detectionPictureTransType"`
  162. DetectionPicturesNumber string `xml:"detectionPicturesNumber"`
  163. IsDataRetransmission string `xml:"isDataRetransmission"`
  164. DurationList struct {
  165. Duration []struct {
  166. RelationEvent string `xml:"relationEvent"`
  167. } `xml:"Duration"`
  168. } `xml:"DurationList"`
  169. }
  170. var sMap = map[string]string{
  171. "shelteralarm": "遮盖报警",
  172. "regionEntrance": "进入区域",
  173. "fielddetection": "区域入侵",
  174. "linedetection": "越界侦测",
  175. }