cow_neck_ring_error.go 9.1 KB

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