single.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. package identify
  2. import (
  3. "encoding/json"
  4. "strconv"
  5. "strings"
  6. )
  7. // SingleItem Nv和Ov的组合规则:
  8. // 1. Nv是什么 || Nv不是什么
  9. // 2. Ov是什么 || Ov不是什么
  10. //
  11. // 1与2的布尔运行结果交叉后, 得到4种组合 00, 01, 10, 11.
  12. // 一个事件的判断, 就处在[00, 01, 10, 11]的其中, 有一项为nil, 则表示该项直接通过
  13. // 多个事件, 就判断多个[00, 01, 10, 11], 所以得出以下结论:
  14. // 针对设备配置如下规则:
  15. //
  16. // {
  17. // "EventName 1": {
  18. // "NvIn": [1,2,3,4],
  19. // "NvNotIn": [5,6,7,8],
  20. // "OvIn": [1,2,3,4],
  21. // "OvNotIn": [5,6,7,8],
  22. // },
  23. // "EventName 2": {
  24. // "NvIn": [1,2,3,4],
  25. // "NvNotIn": [5,6,7,8],
  26. // "OvNotIn": [5,6,7,8],
  27. // },
  28. // ......
  29. // }
  30. type SingleItem struct {
  31. nv string // 当前值
  32. ov string // 上一次的值
  33. rules map[string]Rule
  34. }
  35. func (s *SingleItem) Check(ov, nv string) string {
  36. defer func() {
  37. s.nv = ""
  38. s.ov = ""
  39. }()
  40. s.nv = nv
  41. s.ov = ov
  42. for event, rule := range s.rules {
  43. if s.check(rule) {
  44. return event
  45. }
  46. }
  47. return ""
  48. }
  49. func (s *SingleItem) check(rule Rule) bool {
  50. var ovIn, ovNotIn, nvIn, nvNotIn = true, true, true, true
  51. if rule.OvIn != nil {
  52. ovIn = s.ovIn(rule.OvIn)
  53. }
  54. if rule.OvNotIn != nil {
  55. ovNotIn = s.ovNotIn(rule.OvNotIn)
  56. }
  57. if rule.NvIn != nil {
  58. nvIn = s.nvIn(rule.NvIn)
  59. }
  60. if rule.NvNotIn != nil {
  61. nvNotIn = s.nvNotIn(rule.NvNotIn)
  62. }
  63. return ovIn && ovNotIn && nvIn && nvNotIn
  64. }
  65. func (s *SingleItem) ovIn(slice []string) bool {
  66. b := true
  67. if slice != nil && s.inSlice(slice, s.ov) == false {
  68. b = false
  69. }
  70. return b
  71. }
  72. func (s *SingleItem) ovNotIn(slice []string) bool {
  73. b := true
  74. if slice != nil && s.inSlice(slice, s.ov) == true {
  75. b = false
  76. }
  77. return b
  78. }
  79. func (s *SingleItem) nvIn(slice []string) bool {
  80. b := true
  81. if slice != nil && s.inSlice(slice, s.nv) == false {
  82. b = false
  83. }
  84. return b
  85. }
  86. func (s *SingleItem) nvNotIn(slice []string) bool {
  87. b := true
  88. if slice != nil && s.inSlice(slice, s.nv) == true {
  89. b = false
  90. }
  91. return b
  92. }
  93. func (s *SingleItem) inSlice(slice []string, v string) bool {
  94. for _, s2 := range slice {
  95. if s2 == v {
  96. return true
  97. }
  98. // 数字比较
  99. if _, err := strconv.ParseInt(s2, 10, 64); err != nil {
  100. return s.compare(s2, v)
  101. }
  102. }
  103. return false
  104. }
  105. func (s *SingleItem) compare(r string, v string) bool {
  106. if strings.Index(r, "...") > -1 {
  107. return s.compareRange(r, v)
  108. } else if strings.Index(r, " ") > 1 {
  109. return s.compareLogic(r, v)
  110. }
  111. return false
  112. }
  113. func (s *SingleItem) compareRange(r string, v string) bool {
  114. rl := strings.Split(r, "...")
  115. if len(rl) != 2 {
  116. return false
  117. }
  118. var min, max, vi int64 = 0, 0, 0
  119. if tmin, err := strconv.ParseInt(strings.TrimSpace(rl[0]), 10, 64); err == nil {
  120. min = tmin
  121. } else {
  122. return false
  123. }
  124. if tmax, err := strconv.ParseInt(strings.TrimSpace(rl[1]), 10, 64); err == nil {
  125. max = tmax
  126. } else {
  127. return false
  128. }
  129. if tvi, err := strconv.ParseInt(strings.TrimSpace(v), 10, 64); err == nil {
  130. vi = tvi
  131. } else {
  132. return false
  133. }
  134. return min <= vi && vi <= max
  135. }
  136. func (s *SingleItem) compareLogic(r string, v string) bool {
  137. rl := strings.Split(r, " ")
  138. if len(rl) != 2 {
  139. return false
  140. }
  141. var ri, vi int64 = 0, 0
  142. if tri, err := strconv.ParseInt(strings.TrimSpace(rl[1]), 10, 64); err == nil {
  143. ri = tri
  144. } else {
  145. return false
  146. }
  147. if tvi, err := strconv.ParseInt(strings.TrimSpace(v), 10, 64); err == nil {
  148. vi = tvi
  149. } else {
  150. return false
  151. }
  152. switch rl[0] {
  153. case "<":
  154. return vi < ri
  155. case "<=":
  156. return vi <= ri
  157. case ">":
  158. return vi > ri
  159. case ">=":
  160. return vi >= ri
  161. case "!=":
  162. return vi != ri
  163. }
  164. return false
  165. }
  166. // NewSingleCheck 生成一个检测对象, 之后调用Check来获得事件名称
  167. func NewSingleCheck(rules map[string]Rule) *SingleItem {
  168. return &SingleItem{
  169. rules: rules,
  170. }
  171. }
  172. func StepTest(ov, nv, ruleString string) string {
  173. rules := make(map[string]Rule)
  174. err := json.Unmarshal([]byte(ruleString), &rules)
  175. if err != nil {
  176. println(err.Error())
  177. }
  178. return NewSingleCheck(rules).Check(ov, nv)
  179. }