cow_neck_ring_error.go 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. package crontab
  2. import (
  3. "kpt-pasture/model"
  4. "kpt-pasture/util"
  5. "time"
  6. pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
  7. "gitee.com/xuyiping_admin/pkg/logger/zaplog"
  8. "go.uber.org/zap"
  9. )
  10. // CowNeckRingErrorEnter 异常脖环监控 create_jbq_tj
  11. func (e *Entry) CowNeckRingErrorEnter() (err error) {
  12. pastureList := e.FindPastureList()
  13. if pastureList == nil || len(pastureList) == 0 {
  14. return nil
  15. }
  16. for _, pasture := range pastureList {
  17. e.DB.Model(new(model.NeckRingError)).Delete(new(model.NeckRingError)).Where("pasture_id = ?", pasture.Id)
  18. e.CowNeckRingError(pasture.Id)
  19. zaplog.Error("CowNeckRingErrorEnter-Success", zap.Any("pasture", pasture))
  20. }
  21. return nil
  22. }
  23. func (e *Entry) CowNeckRingError(pastureId int64) {
  24. yesterday := time.Now().Local().AddDate(0, 0, -1).Format(model.LayoutDate2)
  25. habitMinId, originalMinId := 0, 0
  26. if err := e.DB.Model(new(model.NeckActiveHabit)).
  27. Select("MIN(id) as id").
  28. Where("pasture_id = ?", pastureId).
  29. Where("heat_date = ?", yesterday).
  30. Scan(&habitMinId).Error; err != nil {
  31. zaplog.Error("CowNeckRingError-Error", zap.Any("pastureId", pastureId), zap.Any("err", err))
  32. return
  33. }
  34. if err := e.DB.Model(new(model.NeckRingOriginal)).
  35. Select("MIN(id) as id").
  36. Where("pasture_id = ?", pastureId).
  37. Where("heat_date = ?", yesterday).
  38. Scan(&originalMinId).Error; err != nil {
  39. zaplog.Error("CowNeckRingError-Error", zap.Any("pastureId", pastureId), zap.Any("err", err))
  40. return
  41. }
  42. minIsBindDate := util.TimeParseLocalUnix(yesterday)
  43. neckRingList := make([]*model.NeckRing, 0)
  44. if err := e.DB.Model(new(model.NeckRingError)).
  45. Where("pasture_id = ?", pastureId).
  46. Where("is_bind = ?", pasturePb.IsShow_Ok).
  47. Where("wear_at <= ?", minIsBindDate).
  48. Find(&neckRingList).Error; err != nil {
  49. zaplog.Error("NeckRingErrorOfNoSignal", zap.Any("err", err), zap.Any("pastureId", pastureId))
  50. }
  51. updateNeckRingMap := make(map[int64]*model.NeckRingStats)
  52. errorMap := e.NeckRingErrorMap()
  53. for _, neckRing := range neckRingList {
  54. c1 := e.NeckRingErrorOfNoSignal(pastureId, neckRing, int64(habitMinId), yesterday)
  55. if c1 > 0 {
  56. updateNeckRingMap[neckRing.Id] = &model.NeckRingStats{
  57. ErrorKind: c1,
  58. ErrorReason: errorMap[c1],
  59. Describe: "",
  60. }
  61. }
  62. c2 := e.NeckRingErrorOfSuspectedFallOffAndLowBattery(pastureId, neckRing, int64(habitMinId), yesterday)
  63. if c2 > 0 {
  64. updateNeckRingMap[neckRing.Id] = &model.NeckRingStats{
  65. ErrorKind: c2,
  66. ErrorReason: errorMap[c2],
  67. Describe: "",
  68. }
  69. }
  70. c3 := e.NeckRingErrorOfReceivingLess(pastureId, neckRing, int64(habitMinId), int64(originalMinId), yesterday)
  71. if c3 > 0 {
  72. updateNeckRingMap[neckRing.Id] = &model.NeckRingStats{
  73. ErrorKind: c3,
  74. ErrorReason: errorMap[c3],
  75. Describe: "",
  76. }
  77. }
  78. c4 := e.NeckRingErrorOfDataLatency(pastureId, neckRing, int64(habitMinId), yesterday)
  79. if c4 > 0 {
  80. updateNeckRingMap[neckRing.Id] = &model.NeckRingStats{
  81. ErrorKind: c4,
  82. ErrorReason: errorMap[c4],
  83. Describe: "",
  84. }
  85. }
  86. }
  87. if len(updateNeckRingMap) > 0 {
  88. for id, v := range updateNeckRingMap {
  89. if err := e.DB.Model(new(model.NeckRing)).
  90. Where("id = ?", id).
  91. Updates(map[string]interface{}{
  92. "status": pasturePb.IsShow_No,
  93. "error_kind": v.ErrorKind,
  94. "error_reason": v.ErrorReason,
  95. "describe": v.Describe,
  96. }).Error; err != nil {
  97. zaplog.Error("CowNeckRingError", zap.Any("err", err), zap.Any("id", id), zap.Any("v", v))
  98. }
  99. }
  100. }
  101. }
  102. // NeckRingErrorOfNoSignal 佩戴后无信号
  103. func (e *Entry) NeckRingErrorOfNoSignal(pastureId int64, neckRing *model.NeckRing, minId int64, dateTime string) pasturePb.NeckRingNumberError_Kind {
  104. var count int64
  105. if err := e.DB.Model(new(model.NeckActiveHabit)).
  106. Where("id >= ?", minId).
  107. Where("neck_ring_number = ?", neckRing.NeckRingNumber).
  108. Where("pasture_id = ?", pastureId).
  109. Where("heat_date >= ?", dateTime).
  110. Count(&count).Error; err != nil {
  111. zaplog.Error("NeckRingErrorOfNoSignal", zap.Any("err", err), zap.Any("pastureId", pastureId))
  112. }
  113. if count <= 0 {
  114. return pasturePb.NeckRingNumberError_No_Signal
  115. }
  116. return pasturePb.NeckRingNumberError_Invalid
  117. }
  118. // NeckRingErrorOfSuspectedFallOffAndLowBattery 插入异常脖环 '疑似脱落', '电量低','接收少'
  119. func (e *Entry) NeckRingErrorOfSuspectedFallOffAndLowBattery(pastureId int64, neckRing *model.NeckRing, minId int64, dateTime string) pasturePb.NeckRingNumberError_Kind {
  120. nowTime := time.Now().Local()
  121. neckRingHabitList := make([]*model.NeckActiveHabit, 0)
  122. if err := e.DB.Model(new(model.NeckActiveHabit)).
  123. Select(``).
  124. Where("id >= ?", minId).
  125. Where("neck_ring_number = ?", neckRing.NeckRingNumber).
  126. Where("pasture_id = ?", pastureId).
  127. Where("heat_date >= ?", dateTime).
  128. Find(&neckRingHabitList).Error; err != nil {
  129. zaplog.Error("suspectedFallOffAndLowBattery", zap.Any("err", err), zap.Any("pastureId", pastureId))
  130. return pasturePb.NeckRingNumberError_Invalid
  131. }
  132. nba, nb1, nbHh, nbh, voltage := 0, 0, 0, 0, int32(0)
  133. for _, v := range neckRingHabitList {
  134. nba++
  135. if v.High <= 50 && v.Rumina <= 5 {
  136. nb1 += 1
  137. }
  138. at := util.DateTimeParseLocalUnix(v.ActiveTime)
  139. nowTimeUnix := nowTime.Unix()
  140. hoursDiff := (nowTimeUnix - at) / 3600
  141. sumRuminaIntake := v.SumRumina + v.SumIntake
  142. if hoursDiff <= 8 && (v.High > 0 || sumRuminaIntake > 20) {
  143. nbHh++
  144. }
  145. if v.High > 100 || v.Rumina > 5 {
  146. nbh++
  147. }
  148. voltage += v.Voltage
  149. }
  150. svgVoltage := int32(float32(voltage) / float32(nba))
  151. errorKind := pasturePb.NeckRingNumberError_Invalid
  152. switch {
  153. case svgVoltage <= 275:
  154. errorKind = pasturePb.NeckRingNumberError_Low_Battery
  155. case nb1 >= 4:
  156. errorKind = pasturePb.NeckRingNumberError_Suspected_Fall_Off
  157. default:
  158. errorKind = pasturePb.NeckRingNumberError_Receiving_Less
  159. }
  160. if (nb1 >= 4 && nbHh <= 1) || svgVoltage <= 275 || nba <= (5+nowTime.Hour()/4-1) {
  161. return errorKind
  162. }
  163. return pasturePb.NeckRingNumberError_Invalid
  164. }
  165. // NeckRingErrorOfReceivingLess '接收少'
  166. func (e *Entry) NeckRingErrorOfReceivingLess(pastureId int64, neckRing *model.NeckRing, habitMinId, originalMinId int64, dateTime string) pasturePb.NeckRingNumberError_Kind {
  167. var count int64
  168. if err := e.DB.Model(new(model.NeckRing)).
  169. Where("pasture_id = ?", pastureId).
  170. Where("neck_ring_number = ?", neckRing.NeckRingNumber).
  171. Where("status = ?", pasturePb.IsShow_No).
  172. Count(&count).Error; err != nil {
  173. zaplog.Error("NeckRingErrorOfReceivingLess", zap.Any("err", err), zap.Any("pastureId", pastureId))
  174. return pasturePb.NeckRingNumberError_Invalid
  175. }
  176. // 已存在就不再处理
  177. if count > 0 {
  178. return pasturePb.NeckRingNumberError_Invalid
  179. }
  180. if err := e.DB.Model(new(model.NeckActiveHabit)).
  181. Where("id >= ?", habitMinId).
  182. Where("neck_ring_number = ?", neckRing.NeckRingNumber).
  183. Where("pasture_id = ?", pastureId).
  184. Where("heat_date >= ?", dateTime).
  185. Count(&count).Error; err != nil {
  186. zaplog.Error("NeckRingErrorOfReceivingLess", zap.Any("err", err), zap.Any("pastureId", pastureId))
  187. }
  188. // 已存在就不再处理
  189. if count > 0 {
  190. return pasturePb.NeckRingNumberError_Invalid
  191. }
  192. // 查询原始活动数据统计信息
  193. var originalStats struct {
  194. Count int64
  195. AvgVoltage float64
  196. }
  197. if err := e.DB.Model(new(model.NeckRingOriginal)).
  198. Select("COUNT(*) as count, ROUND(AVG(voltage)) as avg_voltage").
  199. Where("id >= ?", originalMinId).
  200. Where("neck_ring_number = ?", neckRing.NeckRingNumber).
  201. Where("pasture_id = ?", pastureId).
  202. Where("heat_date >= ?", dateTime).
  203. First(&originalStats).Error; err != nil {
  204. zaplog.Error("NeckRingOriginal", zap.Any("err", err), zap.Any("pasture_id", pastureId))
  205. return pasturePb.NeckRingNumberError_Invalid
  206. }
  207. // 创建错误记录
  208. errorKind := pasturePb.NeckRingNumberError_Receiving_Less
  209. if originalStats.AvgVoltage <= 285 {
  210. errorKind = pasturePb.NeckRingNumberError_Low_Battery
  211. }
  212. // 限制最大显示数量为99
  213. displayCount := originalStats.Count
  214. if displayCount > 99 {
  215. displayCount = 99
  216. }
  217. if displayCount > 0 {
  218. return errorKind
  219. }
  220. return pasturePb.NeckRingNumberError_Invalid
  221. }
  222. // NeckRingErrorOfDataLatency 数据延迟
  223. func (e *Entry) NeckRingErrorOfDataLatency(pastureId int64, neckRing *model.NeckRing, habitMinId int64, dateTime string) pasturePb.NeckRingNumberError_Kind {
  224. var count int64
  225. if err := e.DB.Model(new(model.NeckActiveHabit)).
  226. Select(`h.cow_id, h.ear_number, SUM(IF(TIMESTAMPDIFF(HOUR, UNIX_TIMESTAMP(h.active_time), h.created_at)>9, 1, 0)) AS nb, COUNT(1) AS nba, ROUND(AVG(h.voltage), 0) AS voltage`).
  227. Where("id >= ?", habitMinId).
  228. Where("cow_id = ?", neckRing.CowId).
  229. Where("filter_high > ?", 200).
  230. Where("heat_date >= ?", dateTime).
  231. Having("nb/nba >= ?", 0.7).
  232. Count(&count).Error; err != nil {
  233. zaplog.Error("NeckRingErrorOfDataLatency", zap.Any("err", err), zap.Any("pastureId", pastureId))
  234. }
  235. if count > 0 {
  236. return pasturePb.NeckRingNumberError_Data_Latency
  237. }
  238. return pasturePb.NeckRingNumberError_Invalid
  239. }