datacaps.go 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. package service
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/redis/go-redis/v9"
  6. "github.com/xuri/excelize/v2"
  7. "log"
  8. "strconv"
  9. "time"
  10. "ydMonitoring/config"
  11. "ydMonitoring/databases"
  12. "ydMonitoring/logger"
  13. "ydMonitoring/util"
  14. )
  15. /*
  16. *
  17. DataCaps
  18. * 得到所有设备的SN并且通过SN得到表名
  19. * z_device_data_sn
  20. * 查找该表内最新的一条数据信息并且查询该设备数据上传时间,并且通过该时间
  21. * 判断前5分钟内的数据是否缺失,如有缺失,直接推送短信告警,并记录在数据库里面(时间、客户名称、SN、数据缺失的时间、是否处理、处理人、处理时间)
  22. * 新增:获取每个t_id的前10条数据进行两两比较,最后一条数据还需与当前时间进行比较判断在设定时间内是否有数据缺失
  23. * 新增:每一个探头当天内只保存一次数据
  24. *数据之间两两比较,如果时间差大于系统设置时间代表缺少数据,则发送微信告警
  25. *
  26. */
  27. var RedisClient *redis.Client
  28. func init() {
  29. RedisClient = redis.NewClient(&redis.Options{
  30. Addr: config.Config.GetString("redis.host"),
  31. Password: config.Config.GetString("redis.password"), // no password set
  32. DB: 0, // use default DB
  33. })
  34. ping := RedisClient.Ping(context.Background())
  35. if ping.Err() != nil {
  36. log.Println("redis连接失败:", ping.Err())
  37. panic("redis连接失败")
  38. }
  39. }
  40. func DataCaps(devices []Device) {
  41. message := make([]string, 0)
  42. // 文件名
  43. var row = 2
  44. filename := fmt.Sprintf("./files/%s.xlsx", time.Now().Format("2006-01-02"))
  45. file, err := excelize.OpenFile(filename)
  46. if err != nil {
  47. file = excelize.NewFile()
  48. // 创建工作区
  49. sheet := "sheet1"
  50. file.NewSheet(sheet)
  51. // 设置列标题
  52. file.SetCellValue(sheet, "A1", "设备SN")
  53. file.SetCellValue(sheet, "B1", "公司名称")
  54. file.SetCellValue(sheet, "C1", "设备名称")
  55. file.SetCellValue(sheet, "D1", "探头")
  56. file.SetCellValue(sheet, "E1", "数据缺失开始时间")
  57. file.SetCellValue(sheet, "F1", "设备型号")
  58. } else {
  59. // 获取最后一行
  60. lastRow, err := getLastRow(file, "sheet1")
  61. if err != nil {
  62. logger.ErrorLogger.Println("获取Excel文件失败:", err)
  63. return
  64. }
  65. row = lastRow + 1
  66. }
  67. deviceSensor := make([]DeviceSensor, 0)
  68. for _, v := range devices {
  69. sql := fmt.Sprintf("select t_sn,t_id,t_pid,t_name from device_sensor where t_sn = %s", v.Tsn)
  70. query, _ := databases.Db.Query(sql)
  71. var sn, t_id, t_pid, t_name string
  72. if query != nil {
  73. for query.Next() {
  74. query.Scan(&sn, &t_id, &t_pid, &t_name)
  75. deviceSensor = append(deviceSensor, DeviceSensor{sn, t_id, t_pid, t_name, v.Tmodel})
  76. }
  77. }
  78. }
  79. for _, sensor := range deviceSensor {
  80. //var t_time string
  81. var t_save_t string
  82. var companyname string
  83. var id string
  84. b, _ := Ignore(sensor.Tsn)
  85. if b {
  86. logger.ErrorLogger.Println("该设备已忽略:", sensor.Tsn)
  87. } else {
  88. // 获取当前时间
  89. now := time.Now()
  90. // 获取昨天同一时间
  91. yesterday := now.AddDate(0, 0, -1)
  92. // 设置时间为昨天的 8:30
  93. yesterdayAtEightThirty := time.Date(yesterday.Year(), yesterday.Month(), yesterday.Day(), 8, 30, 0, 0, yesterday.Location()).Format("2006-01-02 15:04:05")
  94. // 构造今天早上8:30的时间
  95. eightThirtyToday := time.Date(now.Year(), now.Month(), now.Day(), 8, 30, 0, 0, now.Location()).Format("2006-01-02 15:04:05")
  96. sql := fmt.Sprintf("SELECT t_time FROM z_device_data_%s WHERE t_id = '%s' AND t_time >='%v' AND t_time<= '%v' ORDER BY t_time DESC", sensor.Tsn, sensor.TId, yesterdayAtEightThirty, eightThirtyToday)
  97. sqls := fmt.Sprintf("SELECT t_save_t FROM device_parameter WHERE t_sn='%s' ORDER BY update_time DESC LIMIT 1", sensor.Tsn)
  98. company := fmt.Sprintf("SELECT t_name,id FROM company WHERE id='%s'", sensor.TPid)
  99. databases.Db.QueryRow(sqls).Scan(&t_save_t)
  100. databases.Db.QueryRow(company).Scan(&companyname, &id)
  101. rows, err := databases.Db.Query(sql)
  102. if err != nil {
  103. logger.ErrorLogger.Println("查询数据失败:", err)
  104. continue
  105. }
  106. defer rows.Close()
  107. var times []string
  108. for rows.Next() {
  109. var t string
  110. rows.Scan(&t)
  111. times = append(times, t)
  112. }
  113. if len(times) >= 2 {
  114. // 数据之间两两比较,如果时间差大于系统设置时间代表缺少数据,则发送微信告警
  115. timeFormat := "2006-01-02 15:04:05"
  116. for i := 0; i < len(times)-1; i++ {
  117. t1, err := time.Parse(timeFormat, times[i])
  118. if err != nil {
  119. logger.ErrorLogger.Println("解析时间失败:", err)
  120. continue
  121. }
  122. t2, err := time.Parse(timeFormat, times[i+1])
  123. if err != nil {
  124. logger.ErrorLogger.Println("解析时间失败:", err)
  125. continue
  126. }
  127. timeDiff := t1.Sub(t2).Seconds()
  128. float, _ := strconv.ParseFloat(t_save_t, 64) //获取系统设置时间
  129. if timeDiff > float {
  130. fmt.Println("时间差:", timeDiff, "系统设置时间:", float, "设备型号:", sensor.Tmodel)
  131. //生成一个独立的key
  132. key := fmt.Sprintf("%s_%s_%s_%s", sensor.Tsn, companyname+"["+id+"]", sensor.TName, sensor.TId)
  133. //fmt.Println(key)
  134. nowday := time.Now()
  135. midnight := time.Date(nowday.Year(), nowday.Month(), nowday.Day()+1, 0, 0, 0, 0, nowday.Location())
  136. remainingTime := midnight.Sub(nowday)
  137. result, err := RedisClient.SetNX(context.Background(), key, 1, remainingTime).Result()
  138. if err != nil {
  139. logger.ErrorLogger.Println("redis写入失败:", err)
  140. } else if result {
  141. name := sensor.TName + "[" + sensor.Tmodel + "]"
  142. wx := util.WxStruct{
  143. Character: sensor.Tsn,
  144. Thing13: companyname,
  145. Thing3: name,
  146. Thing45: sensor.TId,
  147. Time2: times[i+1],
  148. }
  149. slice := config.Config.GetStringSlice("openID")
  150. for _, v := range slice {
  151. fmt.Println(v, wx)
  152. util.Send(v, wx)
  153. }
  154. message = append(message, fmt.Sprintf("Sn:%s==>%s==>设备:%s==>探头%s==>数据缺失上传时间:%s \n", sensor.Tsn, companyname+"["+id+"]", sensor.TName, sensor.TId, times[i]))
  155. // 将相关信息记录到Excel文件中
  156. if !dataExists(file, "sheet1", sensor.Tsn, companyname+"["+id+"]", sensor.TName, sensor.TId, times[i+1]) {
  157. file.SetCellValue("sheet1", fmt.Sprintf("A%d", row), sensor.Tsn)
  158. file.SetCellValue("sheet1", fmt.Sprintf("B%d", row), companyname+"["+id+"]")
  159. file.SetCellValue("sheet1", fmt.Sprintf("C%d", row), sensor.TName)
  160. file.SetCellValue("sheet1", fmt.Sprintf("D%d", row), sensor.TId)
  161. file.SetCellValue("sheet1", fmt.Sprintf("E%d", row), times[i+1]) // 数据缺失开始时间
  162. file.SetCellValue("sheet1", fmt.Sprintf("F%d", row), sensor.Tmodel) // 设备型号
  163. row++
  164. }
  165. }
  166. }
  167. }
  168. }
  169. }
  170. }
  171. fmt.Println(message, len(message))
  172. // 保存Excel文件
  173. if err := file.SaveAs(filename); err != nil {
  174. logger.ErrorLogger.Println("保存Excel文件失败:", err)
  175. } else {
  176. logger.InfoLogger.Println("Excel文件保存成功,路径:", filename)
  177. }
  178. }
  179. // 检查数据是否已存在
  180. func dataExists(file *excelize.File, sheet string, sn, company, name, id, time string) bool {
  181. rows, err := file.GetRows(sheet)
  182. if err != nil {
  183. logger.ErrorLogger.Println("获取Excel文件行数据失败:", err)
  184. return false
  185. }
  186. for _, row := range rows[1:] { // 跳过表头
  187. if len(row) >= 5 && row[0] == sn && row[1] == company && row[2] == name && row[3] == id && row[4] == time {
  188. return true
  189. }
  190. }
  191. return false
  192. }
  193. // 获取最后一行的行号
  194. func getLastRow(file *excelize.File, sheet string) (int, error) {
  195. rows, err := file.GetRows(sheet)
  196. if err != nil {
  197. return 0, err
  198. }
  199. return len(rows), nil
  200. }
  201. func Ignore(sn string) (bool, error) {
  202. //sql := "SELECT t_sn FROM ignore WHERE t_sn = ?"
  203. sql := fmt.Sprintf("SELECT t_sn FROM `ignore` WHERE t_sn = '%s'", sn)
  204. var tsn string
  205. err := databases.Db.QueryRow(sql).Scan(&tsn)
  206. if err != nil {
  207. return false, err // 其他数据库错误
  208. }
  209. return tsn == sn, nil
  210. }