ipc_event.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. package main
  2. import (
  3. "context"
  4. "time"
  5. "lc/common/mqtt"
  6. "lc/common/onvif/profiles/event"
  7. "lc/common/onvif/soap"
  8. "lc/common/protocol"
  9. )
  10. type EventActuator struct {
  11. parent *LcDevice
  12. ctx context.Context
  13. cancel context.CancelFunc
  14. }
  15. func NewEventActuator(parent *LcDevice) *EventActuator {
  16. ctx, cancel := context.WithCancel(context.Background())
  17. ea := EventActuator{
  18. parent: parent,
  19. ctx: ctx,
  20. cancel: cancel,
  21. }
  22. return &ea
  23. }
  24. func (o *EventActuator) Cancel() {
  25. o.cancel()
  26. }
  27. func (o *EventActuator) EventHandle(XAddr string) {
  28. defer func() {
  29. recover()
  30. if o.parent.EventActuator != nil {
  31. o.parent.EventActuator.Cancel()
  32. o.parent.EventActuator = nil
  33. }
  34. }()
  35. Retry:
  36. //onvif事件
  37. client := soap.NewClient(soap.WithTimeout(time.Second * 0))
  38. client.AddHeader(soap.NewWSSSecurityHeader(o.parent.onvifDev.User, o.parent.onvifDev.Password))
  39. epy := event.NewEventPortType(client, XAddr)
  40. resp0, err0 := epy.GetServiceCapabilities(&event.GetServiceCapabilities{})
  41. if err0 != nil {
  42. return
  43. }
  44. if !resp0.Capabilities.WSPullPointSupport {
  45. return
  46. }
  47. resp1, err1 := epy.GetEventProperties(&event.GetEventProperties{})
  48. if err1 != nil {
  49. return
  50. }
  51. //订阅在onvif.json中Event配置的事件主题
  52. var TopicExpressionDialect event.AnyURI = "https://www.onvif.org/ver10/tev/topicExpression/ConcreteSet"
  53. if len(resp1.TopicExpressionDialect) > 0 && len(resp1.TopicExpressionDialect[0]) > 0 {
  54. TopicExpressionDialect = event.AnyURI(resp1.TopicExpressionDialect[0])
  55. }
  56. cps := event.CreatePullPointSubscription{
  57. Filter: event.FilterType{
  58. TopicExpression: event.TopicExpressionType{
  59. TopicKinds: o.parent.onvifDev.Event,
  60. Dialect: TopicExpressionDialect,
  61. },
  62. },
  63. }
  64. resp2, err2 := epy.CreatePullPointSubscription(&cps)
  65. if err2 != nil {
  66. return
  67. }
  68. pps := event.NewPullPointSubscription(client, string(resp2.SubscriptionReference.Address))
  69. pm := event.PullMessages{MessageLimit: resp0.Capabilities.MaxPullPoints}
  70. errCnt := 0
  71. for {
  72. select {
  73. case <-o.ctx.Done():
  74. return
  75. default:
  76. resp, err := pps.PullMessages(&pm)
  77. if err != nil {
  78. //发生错误,则停3秒再重试
  79. time.Sleep(3 * time.Second)
  80. if errCnt++; errCnt > 5 {
  81. goto Retry
  82. }
  83. break
  84. } else {
  85. errCnt = 0
  86. }
  87. if resp == nil {
  88. break
  89. }
  90. for _, v := range resp.NotificationMessage {
  91. //一键告警按键告警,v.Topic.TopicKinds == "tns1:Device/Trigger/tnshik:AlarmIn"
  92. t, err := time.Parse("2006-01-02T15:04:05Z", v.Message.Message.UtcTime)
  93. if err != nil {
  94. continue
  95. }
  96. ca := protocol.OnvifAlarmInfo{
  97. AlarmTopic: v.Topic.TopicKinds,
  98. Time: protocol.ToBJTime(t).Format("2006-01-02 15:04:05"),
  99. }
  100. if len(v.Message.Message.Source.SimpleItem) > 0 {
  101. ca.Source = make(map[string]string)
  102. for _, si := range v.Message.Message.Source.SimpleItem {
  103. ca.Source[si.Name] = si.Value
  104. }
  105. }
  106. if len(v.Message.Message.Key.SimpleItem) > 0 {
  107. ca.Key = make(map[string]string)
  108. for _, si := range v.Message.Message.Key.SimpleItem {
  109. ca.Key[si.Name] = si.Value
  110. }
  111. }
  112. if len(v.Message.Message.Data.SimpleItem) > 0 {
  113. ca.Data = make(map[string]string)
  114. for _, si := range v.Message.Message.Data.SimpleItem {
  115. ca.Data[si.Name] = si.Value
  116. }
  117. }
  118. seq := GetNextUint64()
  119. var obj protocol.Pack_OnvifAlarm
  120. if str, err := obj.EnCode(o.parent.onvifDev.Code, appConfig.GID, seq, &ca); err == nil {
  121. topic := GetTopic(o.parent.GetDevType(), o.parent.onvifDev.Code, protocol.TP_ONVIF_ALARM)
  122. GetMQTTMgr().Publish(topic, str, mqtt.AtMostOnce, ToAll)
  123. }
  124. switch v.Topic.TopicKinds {
  125. case "tns1:Device/Trigger/tnshik:AlarmIn": //海康一键报警
  126. o.HandleDeviceTriggerAlarm(seq, &ca) //录像抓图
  127. case "tns1:RuleEngine/LineDetector/Crossed": //遮挡告警
  128. o.HandleRuleEngineCrossedLinedetector(seq, &ca)
  129. }
  130. }
  131. }
  132. }
  133. }
  134. func (o *EventActuator) HandleRuleEngineCrossedLinedetector(seq uint64, ca *protocol.OnvifAlarmInfo) {
  135. go o.parent.Snapshot("")
  136. }
  137. func (o *EventActuator) HandleDeviceTriggerAlarm(seq uint64, ca *protocol.OnvifAlarmInfo) {
  138. if v, ok := ca.Data["State"]; ok && v == "true" {
  139. go o.parent.RecordToFLV("", 20) //告警开始,抓拍视频
  140. }
  141. go o.parent.Snapshot("") //告警开始或结束,抓拍图片
  142. }