eventServer.go 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. package eventServer
  2. import (
  3. "encoding/xml"
  4. "errors"
  5. "fmt"
  6. "github.com/sirupsen/logrus"
  7. mail "github.com/xhit/go-simple-mail/v2"
  8. "io"
  9. "io/ioutil"
  10. "lc-fangdaosha/global"
  11. "lc-fangdaosha/model/app"
  12. "lc-fangdaosha/service"
  13. "log"
  14. "math"
  15. "mime/multipart"
  16. "net/http"
  17. "strconv"
  18. "strings"
  19. "time"
  20. )
  21. // MQDEvent (MQTT Data Event) 用于mqtt传输事件
  22. type MQDEvent struct {
  23. EventCode string `json:"eventCode"`
  24. EId int `json:"eId"`
  25. Ip string `json:"ip"`
  26. Type string `json:"type"`
  27. StartTime string `json:"startTime"`
  28. Name string `json:"name"`
  29. Data []byte `json:"data"`
  30. }
  31. func StartEventServer() {
  32. //记录长宽高
  33. go func() {
  34. for {
  35. l, w, h := CalcCap()
  36. dumps := []Constant{
  37. {l, w, h, l * w * h},
  38. }
  39. // 遍历结构体并进行比对
  40. for _, variable := range global.Config.Dump {
  41. bestMatch := FindBestMatch(dumps, Constant{
  42. variable[0], variable[1], variable[2], variable[3],
  43. })
  44. fmt.Println("最匹配的常量数据:", bestMatch)
  45. //todo 保存数据库
  46. var cars []*app.CarInfo
  47. newCar := &app.CarInfo{
  48. Height: bestMatch.Height,
  49. Width: bestMatch.Width,
  50. Length: bestMatch.Length,
  51. Volume: bestMatch.Volume,
  52. Count: 1,
  53. Time: time.Now(),
  54. }
  55. cars = append(cars, newCar) //将新创建的车辆信息添加到cars切片的末尾
  56. // 保存到数据库
  57. carInfoService.Save(cars)
  58. }
  59. fmt.Println("长", l, "宽", w, "高", h)
  60. time.Sleep(500 * time.Millisecond)
  61. }
  62. }()
  63. http.HandleFunc("/event", handler)
  64. logrus.Fatal("事件监听服务启动失败", http.ListenAndServe(":8850", nil))
  65. }
  66. func handler(w http.ResponseWriter, r *http.Request) {
  67. go func() {
  68. //监听主机应答固定,直接先应答
  69. w.WriteHeader(200)
  70. w.Header().Add("Date", time.Now().String())
  71. w.Header().Add("Connection", "close")
  72. }()
  73. logRequest(r)
  74. contentType := r.Header.Get("Content-Type")
  75. if strings.Contains(contentType, "application/xml") {
  76. bytes, err := ioutil.ReadAll(r.Body)
  77. if err != nil {
  78. logrus.Error("事件处理-读取错误:", err)
  79. return
  80. }
  81. var event EventNotificationAlert
  82. err = xml.Unmarshal(bytes, &event)
  83. if err != nil {
  84. logrus.Error("事件处理-解析错误:", err)
  85. return
  86. }
  87. //处理事件 todo 邮箱
  88. handleEvent_(event)
  89. } else if strings.Contains(contentType, "multipart/form-data") {
  90. handleMultipart(r)
  91. } else {
  92. logrus.WithField("Content-Type", contentType).Error("该Content-Type没有写处理逻辑")
  93. return
  94. }
  95. }
  96. //TODO 限制事件重复触发,一段时间内不重复发送邮件,但保持报警状态
  97. var eventService = service.ServiceGroupApp.AppServiceGroup.EventService
  98. var carInfoService = service.ServiceGroupApp.AppServiceGroup.CarInfoService
  99. // 保留小数
  100. func round(num float64, places int) float64 {
  101. shift := math.Pow(10, float64(places))
  102. return math.Round(num*shift) / shift
  103. }
  104. // 保存摄像机获取到的长度,高度,宽度以及时间
  105. var bulk = make(map[string][]float64)
  106. // 处理多文件事件
  107. func handleMultipart(r *http.Request) {
  108. // todo 远程联动
  109. multipartReader := multipart.NewReader(r.Body, "boundary")
  110. var msg string //邮件消息
  111. // 循环读取每个 part
  112. var eventAlert EventNotificationAlert
  113. for {
  114. part, err := multipartReader.NextPart()
  115. fmt.Println("is", errors.Is(err, io.EOF))
  116. fmt.Println("as", errors.As(err, &io.EOF))
  117. if errors.Is(err, io.EOF) {
  118. break
  119. }
  120. if err != nil {
  121. log.Println("Failed to read part:", err)
  122. continue
  123. }
  124. // 检查 part 的 Content-Disposition
  125. formName := part.FormName()
  126. //if formName != "intrusionImage" {
  127. if !strings.Contains(formName, "Image") {
  128. //不含图片的xml部分数据
  129. xmlData, err := ioutil.ReadAll(part)
  130. if err != nil {
  131. return
  132. }
  133. xml.Unmarshal(xmlData, &eventAlert)
  134. msg = handleEvent_(eventAlert)
  135. continue
  136. }
  137. //处理图片部分数据
  138. contentType := part.Header.Get("Content-Type")
  139. eventCode := part.Header.Get("Content-ID")
  140. picName := timeFmt(eventAlert.DateTime) + ".jpeg"
  141. data, _ := ioutil.ReadAll(part)
  142. if strings.Contains(eventAlert.ChannelName, "plateNumber") {
  143. // 识别车牌,记录次数
  144. number, err := CallLicensePlateRecognitionAPI(data)
  145. if err != nil {
  146. fmt.Println("车牌识别失败:", err)
  147. //time.Sleep(1000)
  148. }
  149. //todo 处理车牌号
  150. carInfoService.ProcessPlateNumber(number)
  151. return
  152. }
  153. if strings.Contains(eventAlert.ChannelName, "metering1") {
  154. //测量车的长度和高度
  155. targetRect := eventAlert.DetectionRegionList.DetectionRegionEntry[0].TargetRect
  156. //x, _ := strconv.ParseFloat(targetRect.X, 64)
  157. y, _ := strconv.ParseFloat(targetRect.Y, 64)
  158. h, _ := strconv.ParseFloat(targetRect.Height, 64)
  159. w, _ := strconv.ParseFloat(targetRect.Width, 64)
  160. n := int(round(y+h, 1) * 10)
  161. b := float64(global.Config.Metering.Camera1.B[n])
  162. a := float64(global.Config.Metering.Camera1.A[n])
  163. rh := h / (y + h) * b
  164. rl := w * a
  165. //dateTime := eventAlert.DateTime
  166. //bulk[dateTime] = append(bulk[dateTime], rh, rl)
  167. LhChan <- [2]float64{rl, rh}
  168. return
  169. }
  170. if strings.Contains(eventAlert.ChannelName, "metering2") {
  171. //todo 测量车的宽度
  172. targetRect := eventAlert.DetectionRegionList.DetectionRegionEntry[0].TargetRect
  173. //x, _ := strconv.ParseFloat(targetRect.X, 64)
  174. y, _ := strconv.ParseFloat(targetRect.Y, 64)
  175. h, _ := strconv.ParseFloat(targetRect.Height, 64)
  176. w, _ := strconv.ParseFloat(targetRect.Width, 64)
  177. n := int(round(y+h, 1) * 10)
  178. a := float64(global.Config.Metering.Camera2.A[n])
  179. rw := w * a
  180. WChan <- rw
  181. //dateTime := eventAlert.DateTime
  182. //bulk[dateTime] = append(bulk[dateTime], rw)
  183. //// 识别车牌,记录次数
  184. //number, err := CallLicensePlateRecognitionAPI(data)
  185. //if err != nil {
  186. // fmt.Println("车牌识别失败:", err)
  187. // //time.Sleep(1000)
  188. //}
  189. //// 处理车牌号
  190. //carInfoService.ProcessPlateNumber(number)
  191. return
  192. }
  193. f := &mail.File{
  194. Name: picName,
  195. MimeType: contentType,
  196. Data: data,
  197. Inline: true,
  198. }
  199. picture := &app.Picture{
  200. Name: picName,
  201. Time: time.Now(),
  202. Mime: contentType,
  203. Size: len(data),
  204. }
  205. pictureData := &app.PictureData{
  206. Data: data,
  207. }
  208. event := &app.Event{
  209. EventCode: eventCode,
  210. MacAddress: eventAlert.MacAddress,
  211. EventType: eventAlert.EventType,
  212. }
  213. //保存图片
  214. go eventService.Save(event, picture, pictureData)
  215. //邮件通知
  216. SendAlarmEmail(eventAlert.MacAddress, msg, f)
  217. }
  218. }
  219. func handleEvent_(event EventNotificationAlert) string {
  220. var eType string
  221. if event.EventType == "duration" {
  222. eType = event.DurationList.Duration[0].RelationEvent
  223. } else {
  224. eType = event.EventType
  225. }
  226. return fmt.Sprintf("事件类型:%s,时间:%s", sMap[eType], timeFmt(event.DateTime))
  227. }
  228. func timeFmt(str string) string {
  229. s := strings.Split(str, "T")
  230. t := s[0]
  231. s1 := strings.Split(s[1], ".")
  232. s2 := strings.Split(s1[0], "+")
  233. return t + " " + s2[0]
  234. }
  235. func logRequest(req *http.Request) {
  236. // 打印请求行
  237. fmt.Printf("%s %s %s\n", req.Method, req.URL.Path, req.Proto)
  238. // 打印请求头
  239. for name, headers := range req.Header {
  240. for _, h := range headers {
  241. fmt.Printf("%v: %v\n", name, h)
  242. }
  243. }
  244. // 打印请求体
  245. body, _ := ioutil.ReadAll(req.Body)
  246. fmt.Printf("%s\n", body)
  247. }