123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 |
- package eventServer
- import (
- "encoding/xml"
- "fmt"
- "github.com/sirupsen/logrus"
- mail "github.com/xhit/go-simple-mail/v2"
- "io"
- "io/ioutil"
- "lc-fangdaosha/global"
- "lc-fangdaosha/model/app"
- "lc-fangdaosha/service"
- "log"
- "math"
- "mime/multipart"
- "net/http"
- "strconv"
- "strings"
- "time"
- )
- // MQDEvent (MQTT Data Event) 用于mqtt传输事件
- type MQDEvent struct {
- EventCode string `json:"eventCode"`
- EId int `json:"eId"`
- Ip string `json:"ip"`
- Type string `json:"type"`
- StartTime string `json:"startTime"`
- Name string `json:"name"`
- Data []byte `json:"data"`
- }
- func StartEventServer() {
- //记录长宽高
- go func() {
- for {
- l, w, h := CalcCap()
- time.Sleep(500 * time.Millisecond)
- //todo 根据长宽高估计车厢体积
- fmt.Println("长", l, "宽", w, "高", h)
- }
- }()
- http.HandleFunc("/event", handler)
- logrus.Fatal("事件监听服务启动失败", http.ListenAndServe(":8850", nil))
- }
- 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 {
- logrus.Error("事件处理-读取错误:", err)
- return
- }
- var event EventNotificationAlert
- err = xml.Unmarshal(bytes, &event)
- if err != nil {
- logrus.Error("事件处理-解析错误:", err)
- return
- }
- //处理事件 todo 邮箱
- handleEvent_(event)
- } else if strings.Contains(contentType, "multipart/form-data") {
- handleMultipart(r)
- } else {
- logrus.WithField("Content-Type", contentType).Error("该Content-Type没有写处理逻辑")
- return
- }
- }
- //TODO 限制事件重复触发,一段时间内不重复发送邮件,但保持报警状态
- var eventService = service.ServiceGroupApp.AppServiceGroup.EventService
- var carInfoService = service.ServiceGroupApp.AppServiceGroup.CarInfoService
- // 保留小数
- func round(num float64, places int) float64 {
- shift := math.Pow(10, float64(places))
- return math.Round(num*shift) / shift
- }
- var bulk = make(map[string][]float64)
- // 处理多文件事件
- func handleMultipart(r *http.Request) {
- // todo 远程联动
- multipartReader := multipart.NewReader(r.Body, "boundary")
- var msg string //邮件消息
- // 循环读取每个 part
- var eventAlert EventNotificationAlert
- for {
- part, err := multipartReader.NextPart()
- if err == io.EOF {
- break
- }
- if err != nil {
- log.Println("Failed to read part:", err)
- continue
- }
- // 检查 part 的 Content-Disposition
- formName := part.FormName()
- //if formName != "intrusionImage" {
- if !strings.Contains(formName, "Image") {
- //不含图片的xml部分数据
- xmlData, err := ioutil.ReadAll(part)
- if err != nil {
- return
- }
- xml.Unmarshal(xmlData, &eventAlert)
- msg = handleEvent_(eventAlert)
- continue
- }
- //处理图片部分数据
- contentType := part.Header.Get("Content-Type")
- eventCode := part.Header.Get("Content-ID")
- picName := timeFmt(eventAlert.DateTime) + ".jpeg"
- data, _ := ioutil.ReadAll(part)
- if strings.Contains(eventAlert.ChannelName, "plateNumber") {
- // 识别车牌,记录次数
- number, err := CallLicensePlateRecognitionAPI(data)
- if err != nil {
- fmt.Println("车牌识别失败:", err)
- //time.Sleep(1000)
- }
- //todo 处理车牌号
- carInfoService.ProcessPlateNumber(number)
- return
- }
- if strings.Contains(eventAlert.ChannelName, "metering1") {
- //测量车的长度和高度
- targetRect := eventAlert.DetectionRegionList.DetectionRegionEntry[0].TargetRect
- //x, _ := strconv.ParseFloat(targetRect.X, 64)
- y, _ := strconv.ParseFloat(targetRect.Y, 64)
- h, _ := strconv.ParseFloat(targetRect.Height, 64)
- w, _ := strconv.ParseFloat(targetRect.Width, 64)
- n := int(round(y+h, 1) * 10)
- b := float64(global.Config.Metering.Camera1.B[n])
- a := float64(global.Config.Metering.Camera1.A[n])
- rh := h / (y + h) * b
- rl := w * a
- //dateTime := eventAlert.DateTime
- //bulk[dateTime] = append(bulk[dateTime], rh, rl)
- LhChan <- [2]float64{rl, rh}
- return
- }
- if strings.Contains(eventAlert.ChannelName, "metering2") {
- //todo 测量车的宽度
- targetRect := eventAlert.DetectionRegionList.DetectionRegionEntry[0].TargetRect
- //x, _ := strconv.ParseFloat(targetRect.X, 64)
- y, _ := strconv.ParseFloat(targetRect.Y, 64)
- h, _ := strconv.ParseFloat(targetRect.Height, 64)
- w, _ := strconv.ParseFloat(targetRect.Width, 64)
- n := int(round(y+h, 1) * 10)
- a := float64(global.Config.Metering.Camera2.A[n])
- rw := w * a
- WChan <- rw
- //dateTime := eventAlert.DateTime
- //bulk[dateTime] = append(bulk[dateTime], rw)
- //// 识别车牌,记录次数
- //number, err := CallLicensePlateRecognitionAPI(data)
- //if err != nil {
- // fmt.Println("车牌识别失败:", err)
- // //time.Sleep(1000)
- //}
- //// 处理车牌号
- //carInfoService.ProcessPlateNumber(number)
- return
- }
- f := &mail.File{
- Name: picName,
- MimeType: contentType,
- Data: data,
- Inline: true,
- }
- picture := &app.Picture{
- Name: picName,
- Time: time.Now(),
- Mime: contentType,
- Size: len(data),
- }
- pictureData := &app.PictureData{
- Data: data,
- }
- event := &app.Event{
- EventCode: eventCode,
- MacAddress: eventAlert.MacAddress,
- EventType: eventAlert.EventType,
- }
- //保存图片
- go eventService.Save(event, picture, pictureData)
- //邮件通知
- 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)
- }
|