TaskHandle.go 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969
  1. package controllers
  2. import (
  3. "ColdVerify_local/lib"
  4. "ColdVerify_local/logs"
  5. "ColdVerify_local/models/Device"
  6. "ColdVerify_local/models/Task"
  7. "ColdVerify_local/models/VerifyTemplate"
  8. "fmt"
  9. beego "github.com/beego/beego/v2/server/web"
  10. "math"
  11. "net/http"
  12. "sort"
  13. "strings"
  14. "time"
  15. )
  16. type TaskDataHandleController struct {
  17. beego.Controller
  18. }
  19. /*
  20. 同区域数据缺失
  21. */
  22. // 测点自检 自动添加缺失终端,取关联绑定终端平均复制
  23. func (c *TaskDataHandleController) SSE_Automatically_add_missing_terminal() {
  24. T_task_id := c.GetString("T_task_id") // v26nplogbwt1
  25. println("T_task_id:", T_task_id)
  26. c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream")
  27. c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
  28. c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
  29. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "任务开始......"})
  30. Task_r, err := Task.Read_Task(T_task_id)
  31. if err != nil {
  32. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取任务信息失败!"})
  33. return
  34. }
  35. DeviceClassList_r := Device.Read_DeviceClassList_List_id_By_Terminal(Task_r.T_class, false)
  36. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "终端总共:" + lib.To_string(len(DeviceClassList_r)) + " 正在检查自检探头..."})
  37. for _, class_ := range DeviceClassList_r {
  38. _, cnt := Task.Read_TaskData_ById_List(Task_r.T_task_id, class_.T_sn, class_.T_id, "", "", 0, 1)
  39. if cnt == 0 {
  40. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "找到" + class_.T_id + " " + class_.T_remark + " 自检探头"})
  41. // -----------开始平均复制到
  42. device := Device.DeviceClassList{
  43. T_class: class_.T_class,
  44. T_id: class_.T_id,
  45. T_sn: class_.T_sn,
  46. T_remark: class_.T_remark,
  47. }
  48. c.SetAdjacentDeviceAVGTaskData(T_task_id, device, "", "")
  49. // -----------开始平均复制到结束
  50. }
  51. }
  52. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "完成!"})
  53. // Close the connection
  54. c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
  55. }
  56. // 测点数据自检 自动添加缺失数据,取关联绑定终端平均复制
  57. func (c *TaskDataHandleController) SSE_Automatically_add_missing_data() {
  58. T_task_id := c.GetString("T_task_id") // v26nplogbwt1
  59. c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream")
  60. c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
  61. c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
  62. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "任务开始......"})
  63. Task_r, err := Task.Read_Task(T_task_id)
  64. if err != nil {
  65. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取任务信息失败!"})
  66. return
  67. }
  68. // 时间间隔 s
  69. T_saveT := 60
  70. DeviceClassList_list := Device.Read_DeviceClassList_List_id_By_Terminal(Task_r.T_class, false)
  71. // 分组统计每个sn的数据数量
  72. snList := Device.JoinDeviceClassListSnToString(DeviceClassList_list)
  73. TaskData_Total_GroupBySnId := Task.Read_TaskData_Total_GroupBySnId(Task_r.T_task_id, snList, "", "")
  74. if len(TaskData_Total_GroupBySnId) == 0 {
  75. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "暂无测点需要自检!"})
  76. }
  77. Devicedata_list_MAX := TaskData_Total_GroupBySnId[0].Total
  78. TaskData_Total_GroupBySnId_Map := make(map[string]int64)
  79. for _, v := range TaskData_Total_GroupBySnId {
  80. TaskData_Total_GroupBySnId_Map[v.T_sn] = v.Total
  81. }
  82. startTime, endTime := Task.Read_TaskData_T_time_T_Min_Max(Task_r.T_task_id, TaskData_Total_GroupBySnId[0].T_sn, TaskData_Total_GroupBySnId[0].T_id, "", "")
  83. logs.Println("数据标准数量:", Devicedata_list_MAX)
  84. // 选择 数据缺失的终端
  85. for _, DeviceClassList_r := range DeviceClassList_list {
  86. total, ok := TaskData_Total_GroupBySnId_Map[DeviceClassList_r.T_sn]
  87. if !ok {
  88. // 测点自检事再处理
  89. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: DeviceClassList_r.T_id + " 终端自检数据 , 测点缺失,跳过"})
  90. continue
  91. }
  92. if Devicedata_list_MAX == total {
  93. continue
  94. }
  95. list, cnt := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, DeviceClassList_r.T_sn, DeviceClassList_r.T_id, "", "", 0, 9999)
  96. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: DeviceClassList_r.T_id + " 终端自检数据 ,数据差值:" + lib.To_string(Devicedata_list_MAX-cnt) + " "})
  97. // 开始结束时间不同,直接执行平均复制到
  98. if startTime != list[0].T_time || endTime != list[len(list)-1].T_time {
  99. // -----------开始平均复制到
  100. device := Device.DeviceClassList{
  101. T_class: DeviceClassList_r.T_class,
  102. T_id: DeviceClassList_r.T_id,
  103. T_sn: DeviceClassList_r.T_sn,
  104. T_remark: DeviceClassList_r.T_remark,
  105. }
  106. c.SetAdjacentDeviceAVGTaskData(T_task_id, device, "", "")
  107. // -----------开始平均复制到结束
  108. continue
  109. }
  110. for i := 0; i < len(list)-1; i++ {
  111. current := list[i].T_time
  112. next := list[i+1].T_time
  113. ct, _ := time.Parse("2006-01-02 15:04:05", current)
  114. nt, _ := time.Parse("2006-01-02 15:04:05", next)
  115. interval := nt.Unix() - ct.Unix()
  116. //logs.Debug("时间间隔:", interval, "保存时间:", saveTime)
  117. //fmt.Println("当前:", current, "下一个:", next)
  118. // 缺一个时间点 补漏
  119. if int(interval) == 2*T_saveT {
  120. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "找到自检时间点 " + current + " ~ " + next + " 开始自检"})
  121. t := ct.Add(time.Second * time.Duration(T_saveT)).Format("2006-01-02 15:04") //时间临时变量
  122. ttt := (list[i].T_t + list[i+1].T_t) / 2
  123. trht := (list[i].T_rh + list[i+1].T_rh) / 2
  124. Task.InsertTaskData(Task_r.T_task_id, Task.TaskData_{
  125. T_sn: list[i].T_sn,
  126. T_id: list[i].T_id,
  127. T_t: ttt,
  128. T_rh: trht,
  129. T_time: t,
  130. })
  131. continue
  132. }
  133. // 缺的数据大于一个时间点,执行平均复制到
  134. if int(interval) > T_saveT {
  135. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "找到自检时间点 " + current + " ~ " + next + " 开始自检"})
  136. // -----------开始平均复制到
  137. device := Device.DeviceClassList{
  138. T_class: DeviceClassList_r.T_class,
  139. T_id: DeviceClassList_r.T_id,
  140. T_sn: DeviceClassList_r.T_sn,
  141. T_remark: DeviceClassList_r.T_remark,
  142. }
  143. c.SetAdjacentDeviceAVGTaskData(T_task_id, device, "", "")
  144. // -----------开始平均复制到结束
  145. // 平均复制结束,跳出循环
  146. break
  147. }
  148. }
  149. }
  150. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "完成!"})
  151. // Close the connection
  152. c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
  153. }
  154. // 数据持续时间 x 分钟 没有变化
  155. func (c *TaskDataHandleController) SSE_Continuously_unchanged_data() {
  156. T_task_id := c.GetString("T_task_id") // v26nplogbwt1
  157. T_timeout, _ := c.GetInt("T_timeout", 30) // 持续时间
  158. c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream")
  159. c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
  160. c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
  161. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "任务开始......"})
  162. Task_r, err := Task.Read_Task(T_task_id)
  163. if err != nil {
  164. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取任务信息失败!"})
  165. return
  166. }
  167. // 获取 备注 下面关联设备,数量
  168. DeviceClassList_list := Device.Read_DeviceClassList_List_id_By_Terminal(Task_r.T_class, false)
  169. // 选择 数据缺失的终端
  170. var DeleteDeviceClassList []Device.DeviceClassList
  171. for _, DeviceClassList_r := range DeviceClassList_list {
  172. TaskData_list, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, DeviceClassList_r.T_sn, DeviceClassList_r.T_id, "", "", 0, 9999)
  173. if len(TaskData_list) == 0 {
  174. continue
  175. }
  176. maxCount, start, end := Task.FindUnchangedInterval(TaskData_list)
  177. if maxCount > T_timeout {
  178. Task.DeleteTaskDataByTimeRange(T_task_id, DeviceClassList_r.T_sn, DeviceClassList_r.T_id, "", "")
  179. DeleteDeviceClassList = append(DeleteDeviceClassList, DeviceClassList_r)
  180. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "找到" + DeviceClassList_r.T_id + " 探头, " +
  181. "最多连续 " + lib.To_string(maxCount) + " 分钟没有变化," +
  182. "开始时间:" + start + " 结束时间:" + end + "," +
  183. "开始自检"})
  184. }
  185. }
  186. for _, class_ := range DeleteDeviceClassList {
  187. // -----------开始平均复制到
  188. device := Device.DeviceClassList{
  189. T_class: class_.T_class,
  190. T_id: class_.T_id,
  191. T_sn: class_.T_sn,
  192. T_remark: class_.T_remark,
  193. }
  194. c.SetAdjacentDeviceAVGTaskData(T_task_id, device, "", "")
  195. // -----------开始平均复制到结束
  196. }
  197. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "完成!"})
  198. // Close the connection
  199. c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
  200. }
  201. // 绑定点与终端比对 (绑定点数据自检) 终端数据为参照物,绑定点数据在终端偏差±1℃,保温箱为±0.5℃
  202. func (c *TaskDataHandleController) SSE_Comparison_between_binding_points_and_terminals() {
  203. T_task_id := c.GetString("T_task_id") // v26nplogbwt1
  204. T_deviation, _ := c.GetFloat("T_deviation", 1.0) // 误差绑定点数据与终端对比偏差
  205. c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream")
  206. c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
  207. c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
  208. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "任务开始......"})
  209. Task_r, err := Task.Read_Task(T_task_id)
  210. if err != nil {
  211. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取任务信息失败!"})
  212. return
  213. }
  214. // 保温箱偏差为0.5
  215. if Task_r.T_device_type == "X" {
  216. T_deviation = 0.5
  217. }
  218. // -------------------- 获取开始时间--------------------
  219. 温度控制范围最高值 := float64(lib.To_float32(VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "温度控制范围最高值")))
  220. if 温度控制范围最高值 == 0 {
  221. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温度控制范围最高值 标签值不正确!"})
  222. return
  223. }
  224. // 均匀性布点 产品存放区域测点
  225. 部点终端_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "均匀性布点")
  226. 部点终端_list = append(部点终端_list, Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "产品存放区域测点")...)
  227. 部点终端_list = append(部点终端_list, Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "作业出入口总测点")...)
  228. 部点终端_list = Device.DeduplicateById(部点终端_list)
  229. if len(部点终端_list) <= 2 {
  230. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "均匀性布点,产品存放区域测点 太少了,至少两条以上!"})
  231. return
  232. }
  233. 开始时间 := ""
  234. // 开始时间 获取温度下降到第二个低点时间
  235. // 1. 获取温度平均值
  236. 部点终端_sn_list := []string{}
  237. for _, v := range 部点终端_list {
  238. 部点终端_sn_list = append(部点终端_sn_list, v.T_sn)
  239. }
  240. list := Task.Read_TaskData_ById_AVG(Task_r.T_task_id, strings.Join(部点终端_sn_list, "|"), "", "")
  241. if len(list) < 2 {
  242. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "均匀性布点+产品存放区域测点 数据平均值 少于2条!"})
  243. return
  244. }
  245. // 找平均值低于温度控制范围最高值的第二个最低点
  246. lowPoint := 0
  247. for i := 1; i <= len(list)-2; i++ {
  248. if list[i].T_t < list[i-1].T_t && list[i].T_t < list[i+1].T_t && list[i].T_t < float32(温度控制范围最高值) {
  249. lowPoint += 1
  250. }
  251. if lowPoint == 2 {
  252. 开始时间 = list[i].T_time
  253. break
  254. }
  255. }
  256. if len(开始时间) == 0 {
  257. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 开始时间 数据!"})
  258. return
  259. }
  260. // -------------------- 获取开始时间结束 --------------------
  261. 结束时间 := VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "开空开")
  262. if len(结束时间) == 0 {
  263. 结束时间 = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "开满开")
  264. }
  265. if len(结束时间) == 0 {
  266. 结束时间 = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "现场测试结束时间")
  267. }
  268. if len(结束时间) == 0 {
  269. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到结束时间 标签!"})
  270. return
  271. }
  272. 监测终端_list := Device.Read_DeviceClassList_List_id_By_Terminal(Task_r.T_class, true)
  273. if len(监测终端_list) < 1 {
  274. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 监测终端!"})
  275. }
  276. // 查询监测终端开始时间
  277. for i, 监测终端 := range 监测终端_list {
  278. // -------------------- 温湿度绑定点 --------------------
  279. 温湿度绑定点_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "温湿度绑定点"+lib.To_string(i+1))
  280. if len(温湿度绑定点_list) != 1 {
  281. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温湿度绑定点" + lib.To_string(i+1) + " 中找到 " + lib.To_string(len(温湿度绑定点_list)) + "条,只允许 一条数据!"})
  282. }
  283. TaskData_Total_GroupBySnId := Task.Read_TaskData_Total_GroupBySnId(Task_r.T_task_id, 温湿度绑定点_list[0].T_sn, "", "")
  284. if len(TaskData_Total_GroupBySnId) == 0 {
  285. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温湿度绑定点" + lib.To_string(i+1) + " 无数据!请先处理数据!"})
  286. }
  287. fmt.Println("温湿度绑定点"+lib.To_string(i+1)+"数据准备:", 温湿度绑定点_list[0].T_id, 监测终端.T_id, 开始时间, 结束时间)
  288. var 温湿度绑定点vga, 监测终端vga, vgaca float64
  289. 温湿度绑定点vga = Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点_list[0].T_sn, 温湿度绑定点_list[0].T_id, 开始时间, 结束时间)
  290. 监测终端vga = Task.Read_TaskData_AVG(T_task_id, 监测终端.T_sn, 监测终端.T_id, 开始时间, 结束时间)
  291. vgaca = RoundToDecimal(监测终端vga-温湿度绑定点vga, 1)
  292. for T_deviation < math.Abs(vgaca) {
  293. // 缩放
  294. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行缩放 数据!" +
  295. "温湿度绑定点" + lib.To_string(i+1) + " 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " +
  296. "监测终端0" + lib.To_string(i+1) + " 平均值" + lib.To_string(监测终端vga) + "℃ " +
  297. "数据偏差: " + lib.To_string(vgaca) + "℃ " +
  298. "设置:" + lib.To_string(T_deviation) + "℃"})
  299. // 获取缩放度
  300. compress := RoundToDecimal((监测终端vga-T_deviation-0.1)/温湿度绑定点vga, 2)
  301. // 缩放
  302. Task.UpdateTaskDataTemperatureAndHumidityByGeometric_id(T_task_id, 温湿度绑定点_list[0].T_id, "", "", compress)
  303. // 偏移
  304. 温湿度绑定点vga = Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点_list[0].T_sn, 温湿度绑定点_list[0].T_id, 开始时间, 结束时间)
  305. 监测终端vga = Task.Read_TaskData_AVG(T_task_id, 监测终端.T_sn, 监测终端.T_id, 开始时间, 结束时间)
  306. vgaca = math.Round((监测终端vga-温湿度绑定点vga)*100) / 100.0
  307. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行偏移 数据!" +
  308. "温湿度绑定点1 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " +
  309. "监测终端0" + lib.To_string(i+1) + " 平均值" + lib.To_string(监测终端vga) + "℃ " +
  310. "数据偏差: " + lib.To_string(vgaca) + "℃ " +
  311. "设置:" + lib.To_string(T_deviation) + "℃"})
  312. Task.UpdateTaskDataTemperatureAndHumidityByGeometricAVG(T_task_id, 温湿度绑定点_list[0].T_id, "", "", math.Round(((监测终端vga-温湿度绑定点vga)*0.8)*100)/100.0)
  313. 温湿度绑定点vga = Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点_list[0].T_sn, 温湿度绑定点_list[0].T_id, 开始时间, 结束时间)
  314. 监测终端vga = Task.Read_TaskData_AVG(T_task_id, 监测终端.T_sn, 监测终端.T_id, 开始时间, 结束时间)
  315. vgaca = RoundToDecimal(监测终端vga-温湿度绑定点vga, 1)
  316. }
  317. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "数据满足要求!" +
  318. "温湿度绑定点" + lib.To_string(i+1) + " 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " +
  319. "监测终端0" + lib.To_string(i+1) + " 平均值" + lib.To_string(监测终端vga) + "℃ " +
  320. "数据偏差: " + lib.To_string(vgaca) + "℃ !"})
  321. }
  322. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "完成!"})
  323. // Close the connection
  324. c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
  325. }
  326. // 绑定点与冷热点比对 (冷热点数据自检)绑定点数据为参照物,绑定点数据在终端偏差±1℃,保温箱为±0.5℃
  327. func (c *TaskDataHandleController) SSE_Compare_binding_points_with_cold_and_hot_spots() {
  328. T_task_id := c.GetString("T_task_id") // v26nplogbwt1
  329. T_deviation, _ := c.GetFloat("T_deviation", 1.0) // 偏差时间
  330. c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream")
  331. c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
  332. c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
  333. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "任务开始......"})
  334. Task_r, err := Task.Read_Task(T_task_id)
  335. if err != nil {
  336. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取任务信息失败!"})
  337. return
  338. }
  339. // 保温箱偏差为0.5
  340. if Task_r.T_device_type == "X" {
  341. T_deviation = 0.5
  342. }
  343. 温度控制范围最高值 := float64(lib.To_float32(VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "温度控制范围最高值")))
  344. if 温度控制范围最高值 == 0 {
  345. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温度控制范围最高值 标签值不正确!"})
  346. return
  347. }
  348. // 均匀性布点 产品存放区域测点
  349. 部点终端_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "均匀性布点")
  350. 部点终端_list = append(部点终端_list, Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "产品存放区域测点")...)
  351. 部点终端_list = append(部点终端_list, Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "作业出入口总测点")...)
  352. 部点终端_list = Device.DeduplicateById(部点终端_list)
  353. 开始时间 := ""
  354. // 开始时间 获取温度下降到第二个低点时间
  355. // 1. 获取温度平均值
  356. 部点终端_sn_list := []string{}
  357. for _, v := range 部点终端_list {
  358. 部点终端_sn_list = append(部点终端_sn_list, v.T_sn)
  359. }
  360. list := Task.Read_TaskData_ById_AVG(Task_r.T_task_id, strings.Join(部点终端_sn_list, "|"), "", "")
  361. if len(list) < 2 {
  362. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "均匀性布点+产品存放区域测点 数据平均值 少于2条!"})
  363. return
  364. }
  365. // 找平均值低于温度控制范围最高值的第二个最低点
  366. lowPoint := 0
  367. for i := 1; i <= len(list)-2; i++ {
  368. if list[i].T_t < list[i-1].T_t && list[i].T_t < list[i+1].T_t && list[i].T_t < float32(温度控制范围最高值) {
  369. lowPoint += 1
  370. }
  371. if lowPoint == 2 {
  372. 开始时间 = list[i].T_time
  373. break
  374. }
  375. }
  376. if len(开始时间) == 0 {
  377. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 开始时间 数据!"})
  378. return
  379. }
  380. // ------------------
  381. 结束时间 := VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "开空开")
  382. if len(结束时间) == 0 {
  383. 结束时间 = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "开满开")
  384. }
  385. if len(结束时间) == 0 {
  386. 结束时间 = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "现场测试结束时间")
  387. }
  388. if len(结束时间) == 0 {
  389. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到结束时间 标签!"})
  390. return
  391. }
  392. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "--- 开始时间--- " + 开始时间})
  393. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "--- 结束时间--- " + 结束时间})
  394. if len(部点终端_list) <= 2 {
  395. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "均匀性布点,产品存放区域测点 太少了,至少两条以上!"})
  396. return
  397. }
  398. type AVGClassList struct {
  399. T_id string
  400. T_vga float64
  401. }
  402. var AVGClassList_r []AVGClassList
  403. for _, i2 := range 部点终端_list {
  404. AVGClassList_r = append(AVGClassList_r, AVGClassList{T_id: i2.T_id, T_vga: Task.Read_TaskData_AVG(T_task_id, i2.T_sn, i2.T_id, 开始时间, 结束时间)})
  405. }
  406. // 使用 sort.Slice 对切片进行排序
  407. sort.Slice(AVGClassList_r, func(i, j int) bool {
  408. return AVGClassList_r[i].T_vga > AVGClassList_r[j].T_vga // 降序排序
  409. // 如果需要降序排序,可以使用:return AVGClassList_r[i].T_vga > AVGClassList_r[j].T_vga
  410. })
  411. fmt.Println("AVGClassList_r:", AVGClassList_r)
  412. // ------- 温湿度绑定点
  413. 温湿度绑定点1_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "温湿度绑定点1")
  414. if len(温湿度绑定点1_list) != 1 {
  415. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "温湿度绑定点1 中找到 " + lib.To_string(len(温湿度绑定点1_list)) + "条,布点终端异常!"})
  416. return
  417. }
  418. 温湿度绑定点2_list_is := true
  419. 温湿度绑定点2_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "温湿度绑定点2")
  420. if len(温湿度绑定点2_list) != 1 {
  421. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "温湿度绑定点2 没找到,将 温湿度绑定点1 设置低点"})
  422. 温湿度绑定点2_list = 温湿度绑定点1_list
  423. 温湿度绑定点2_list_is = false
  424. }
  425. TaskData_Total_GroupBySnId := Task.Read_TaskData_Total_GroupBySnId(T_task_id, fmt.Sprintf("%s|%s", 温湿度绑定点1_list[0].T_sn, 温湿度绑定点2_list[0].T_sn), 开始时间, 结束时间)
  426. if len(TaskData_Total_GroupBySnId) == 0 {
  427. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温湿度绑定点 无数据"})
  428. return
  429. }
  430. for _, v := range TaskData_Total_GroupBySnId {
  431. if v.Total == 0 {
  432. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温湿度绑定点[" + v.T_id + "] 无数据"})
  433. return
  434. }
  435. }
  436. 温湿度绑定点1vga := Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点1_list[0].T_sn, 温湿度绑定点1_list[0].T_id, 开始时间, 结束时间)
  437. 温湿度绑定点2vga := Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点2_list[0].T_sn, 温湿度绑定点2_list[0].T_id, 开始时间, 结束时间)
  438. if 温湿度绑定点1vga == 温湿度绑定点2vga {
  439. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "温湿度绑定点1 与 温湿度绑定点2 平均值相等,将 进行上下偏移处理!"})
  440. 温湿度绑定点1vga += T_deviation / 2
  441. 温湿度绑定点2vga -= T_deviation / 2
  442. T_deviation /= 2
  443. }
  444. var 温湿度绑定点vga_H, 温湿度绑定点vga_L AVGClassList
  445. if 温湿度绑定点1vga > 温湿度绑定点2vga {
  446. 温湿度绑定点vga_H.T_id = 温湿度绑定点1_list[0].T_id
  447. 温湿度绑定点vga_H.T_vga = 温湿度绑定点1vga
  448. 温湿度绑定点vga_L.T_id = 温湿度绑定点2_list[0].T_id
  449. 温湿度绑定点vga_L.T_vga = 温湿度绑定点2vga
  450. } else {
  451. 温湿度绑定点vga_L.T_id = 温湿度绑定点1_list[0].T_id
  452. 温湿度绑定点vga_L.T_vga = 温湿度绑定点1vga
  453. 温湿度绑定点vga_H.T_id = 温湿度绑定点2_list[0].T_id
  454. 温湿度绑定点vga_H.T_vga = 温湿度绑定点2vga
  455. }
  456. fmt.Println("温湿度绑定点:", 温湿度绑定点vga_H, 温湿度绑定点vga_L)
  457. // -------------------- 温湿度绑定点vga_H --------------------
  458. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "------ 进行 高点处理 ------"})
  459. var vgaca float64
  460. vgaca = math.Round((温湿度绑定点vga_H.T_vga-AVGClassList_r[0].T_vga)*100) / 100.0
  461. for T_deviation < math.Abs(vgaca) {
  462. // 缩放
  463. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行缩放 数据!热点" + lib.To_string(AVGClassList_r[0].T_id) +
  464. " 平均值:" + lib.To_string(AVGClassList_r[0].T_vga) + "℃ " +
  465. "高点 " + lib.To_string(温湿度绑定点vga_H.T_id) +
  466. " 平均值" + lib.To_string(fmt.Sprintf("%.2f", 温湿度绑定点vga_H.T_vga)) + "℃ " +
  467. "数据偏差: " + lib.To_string(vgaca) + "℃ " +
  468. "设置:" + lib.To_string(T_deviation) + "℃"})
  469. Task.UpdateTaskDataTemperatureAndHumidityByGeometric_id(T_task_id, AVGClassList_r[0].T_id, "", "", 0.95)
  470. // 偏移
  471. // 均匀性布点 产品存放区域测点
  472. AVGClassList_r = AVGClassList_r[:0] // 清空切片
  473. for _, i2 := range 部点终端_list {
  474. AVGClassList_r = append(AVGClassList_r, AVGClassList{T_id: i2.T_id, T_vga: Task.Read_TaskData_AVG(T_task_id, i2.T_sn, i2.T_id, 开始时间, 结束时间)})
  475. }
  476. // 使用 sort.Slice 对切片进行排序
  477. sort.Slice(AVGClassList_r, func(i, j int) bool {
  478. return AVGClassList_r[i].T_vga > AVGClassList_r[j].T_vga // 降序排序
  479. // 如果需要降序排序,可以使用:return AVGClassList_r[i].T_vga > AVGClassList_r[j].T_vga
  480. })
  481. fmt.Println("AVGClassList_r:", AVGClassList_r)
  482. vgaca = math.Round((温湿度绑定点vga_H.T_vga-AVGClassList_r[0].T_vga)*100) / 100.0
  483. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行偏移 数据!热点" + lib.To_string(AVGClassList_r[0].T_id) + " 平均值:" + lib.To_string(AVGClassList_r[0].T_vga) +
  484. "℃ 高点 " + lib.To_string(温湿度绑定点vga_H.T_id) + " 平均值" + lib.To_string(温湿度绑定点vga_H.T_vga) + "℃ 数据偏差: " + lib.To_string(vgaca) + "℃ 设置:" + lib.To_string(T_deviation) + "℃"})
  485. Task.UpdateTaskDataTemperatureAndHumidityByGeometricAVG(T_task_id, AVGClassList_r[0].T_id, "", "", math.Round(((vgaca)*0.8)*100)/100.0)
  486. // 均匀性布点 产品存放区域测点
  487. AVGClassList_r = AVGClassList_r[:0] // 清空切片
  488. for _, i2 := range 部点终端_list {
  489. AVGClassList_r = append(AVGClassList_r, AVGClassList{T_id: i2.T_id, T_vga: Task.Read_TaskData_AVG(T_task_id, i2.T_sn, i2.T_id, 开始时间, 结束时间)})
  490. }
  491. // 使用 sort.Slice 对切片进行排序
  492. sort.Slice(AVGClassList_r, func(i, j int) bool {
  493. return AVGClassList_r[i].T_vga > AVGClassList_r[j].T_vga // 降序排序
  494. // 如果需要降序排序,可以使用:return AVGClassList_r[i].T_vga > AVGClassList_r[j].T_vga
  495. })
  496. fmt.Println("AVGClassList_r:", AVGClassList_r)
  497. vgaca = math.Round((温湿度绑定点vga_H.T_vga-AVGClassList_r[0].T_vga)*100) / 100.0
  498. }
  499. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "热点 数据满足要求!" +
  500. "热点" + lib.To_string(AVGClassList_r[0].T_id) +
  501. " 平均值:" + lib.To_string(AVGClassList_r[0].T_vga) + "℃ " +
  502. "高点 " + lib.To_string(温湿度绑定点vga_H.T_id) +
  503. " 平均值" + lib.To_string(fmt.Sprintf("%.2f", 温湿度绑定点vga_H.T_vga)) + "℃ " +
  504. "数据偏差: " + lib.To_string(vgaca) + "℃ "})
  505. // -------------------- 温湿度绑定点vga_L --------------------
  506. if !温湿度绑定点2_list_is {
  507. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "低点跳过处理!"})
  508. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "完成!"})
  509. return
  510. }
  511. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "------ 进行 低点处理 ------"})
  512. vgaca = math.Round((温湿度绑定点vga_L.T_vga-AVGClassList_r[len(AVGClassList_r)-1].T_vga)*100) / 100.0
  513. for T_deviation < math.Abs(vgaca) {
  514. // 缩放
  515. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行缩放 数据!" +
  516. "冷点" + lib.To_string(AVGClassList_r[len(AVGClassList_r)-1].T_id) +
  517. " 平均值:" + lib.To_string(AVGClassList_r[len(AVGClassList_r)-1].T_vga) + "℃ " +
  518. "低点 " + lib.To_string(温湿度绑定点vga_L.T_id) +
  519. " 平均值" + lib.To_string(温湿度绑定点vga_L.T_vga) + "℃ " +
  520. "数据偏差: " + lib.To_string(vgaca) + "℃ " +
  521. "设置:" + lib.To_string(T_deviation) + "℃"})
  522. Task.UpdateTaskDataTemperatureAndHumidityByGeometric_id(T_task_id, AVGClassList_r[len(AVGClassList_r)-1].T_id, "", "", 0.95)
  523. // 偏移
  524. // 均匀性布点 产品存放区域测点
  525. AVGClassList_r = AVGClassList_r[:0] // 清空切片
  526. for _, i2 := range 部点终端_list {
  527. AVGClassList_r = append(AVGClassList_r, AVGClassList{T_id: i2.T_id, T_vga: Task.Read_TaskData_AVG(T_task_id, i2.T_sn, i2.T_id, 开始时间, 结束时间)})
  528. }
  529. // 使用 sort.Slice 对切片进行排序
  530. sort.Slice(AVGClassList_r, func(i, j int) bool {
  531. return AVGClassList_r[i].T_vga > AVGClassList_r[j].T_vga // 降序排序
  532. // 如果需要降序排序,可以使用:return AVGClassList_r[i].T_vga > AVGClassList_r[j].T_vga
  533. })
  534. fmt.Println("AVGClassList_r:", AVGClassList_r)
  535. vgaca = math.Round((温湿度绑定点vga_L.T_vga-AVGClassList_r[len(AVGClassList_r)-1].T_vga)*100) / 100.0
  536. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行偏移 数据!冷点" + lib.To_string(AVGClassList_r[len(AVGClassList_r)-1].T_id) + " 平均值:" + lib.To_string(AVGClassList_r[len(AVGClassList_r)-1].T_vga) +
  537. "℃ 低点 " + lib.To_string(温湿度绑定点vga_L.T_id) + " 平均值" + lib.To_string(温湿度绑定点vga_L.T_vga) + "℃ 数据偏差: " + lib.To_string(vgaca) + "℃ 设置:" + lib.To_string(T_deviation) + "℃"})
  538. Task.UpdateTaskDataTemperatureAndHumidityByGeometricAVG(T_task_id, AVGClassList_r[len(AVGClassList_r)-1].T_id, "", "", math.Round(((vgaca)*0.8)*100)/100.0)
  539. // 均匀性布点 产品存放区域测点
  540. AVGClassList_r = AVGClassList_r[:0] // 清空切片
  541. for _, i2 := range 部点终端_list {
  542. AVGClassList_r = append(AVGClassList_r, AVGClassList{T_id: i2.T_id, T_vga: Task.Read_TaskData_AVG(T_task_id, i2.T_sn, i2.T_id, 开始时间, 结束时间)})
  543. }
  544. // 使用 sort.Slice 对切片进行排序
  545. sort.Slice(AVGClassList_r, func(i, j int) bool {
  546. return AVGClassList_r[i].T_vga > AVGClassList_r[j].T_vga // 降序排序
  547. // 如果需要降序排序,可以使用:return AVGClassList_r[i].T_vga > AVGClassList_r[j].T_vga
  548. })
  549. fmt.Println("AVGClassList_r:", AVGClassList_r)
  550. vgaca = math.Round((温湿度绑定点vga_L.T_vga-AVGClassList_r[len(AVGClassList_r)-1].T_vga)*100) / 100.0
  551. }
  552. //lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "冷点 数据满足要求!冷点" + lib.To_string(AVGClassList_r[len(AVGClassList_r)-1].T_id) + " 平均值:" + lib.To_string(AVGClassList_r[len(AVGClassList_r)-1].T_vga) +
  553. // "℃ 低点 " + lib.To_string(温湿度绑定点vga_L.T_id) + " 平均值" + lib.To_string(温湿度绑定点vga_L.T_vga) + "℃ 数据偏差: " + lib.To_string(vgaca) + "℃ "})
  554. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "完成!"})
  555. // Close the connection
  556. c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
  557. }
  558. // 区间数据校正 (布点区域数据自检) 均匀性布点,产品存放区域测点 区间数据超标校正 超标数据偏移到区间内
  559. func (c *TaskDataHandleController) SSE_Interval_data_correction() {
  560. T_task_id := c.GetString("T_task_id") // v26nplogbwt1
  561. c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream")
  562. c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
  563. c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
  564. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "任务开始......"})
  565. Task_r, err := Task.Read_Task(T_task_id)
  566. if err != nil {
  567. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取任务信息失败!"})
  568. return
  569. }
  570. 结束时间 := VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "开空开")
  571. if len(结束时间) == 0 {
  572. 结束时间 = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "开满开")
  573. }
  574. if len(结束时间) == 0 {
  575. 结束时间 = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "现场测试结束时间")
  576. }
  577. if len(结束时间) == 0 {
  578. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到结束时间 标签!"})
  579. return
  580. }
  581. 温度控制范围最小值 := float64(lib.To_float32(VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "温度控制范围最小值")))
  582. 温度控制范围最高值 := float64(lib.To_float32(VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "温度控制范围最高值")))
  583. if 温度控制范围最小值 == 0 || 温度控制范围最高值 == 0 {
  584. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温度控制范围 标签值不正确!"})
  585. return
  586. }
  587. // 均匀性布点 产品存放区域测点
  588. 部点终端_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "均匀性布点")
  589. 部点终端_list = append(部点终端_list, Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "产品存放区域测点")...)
  590. 部点终端_list = append(部点终端_list, Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "作业出入口总测点")...)
  591. 部点终端_list = Device.DeduplicateById(部点终端_list)
  592. if len(部点终端_list) <= 2 {
  593. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "均匀性布点,产品存放区域测点 太少了,至少两条以上!"})
  594. return
  595. }
  596. 开始时间 := ""
  597. // 开始时间 获取温度下降到第二个低点时间
  598. // 1. 获取温度平均值
  599. 部点终端_sn_list := []string{}
  600. for _, v := range 部点终端_list {
  601. 部点终端_sn_list = append(部点终端_sn_list, v.T_sn)
  602. }
  603. list := Task.Read_TaskData_ById_AVG(Task_r.T_task_id, strings.Join(部点终端_sn_list, "|"), "", "")
  604. if len(list) < 2 {
  605. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "均匀性布点+产品存放区域测点 数据平均值 少于2条!"})
  606. return
  607. }
  608. // 找平均值低于温度控制范围最高值的第二个最低点
  609. lowPoint := 0
  610. for i := 1; i <= len(list)-2; i++ {
  611. if list[i].T_t < list[i-1].T_t && list[i].T_t < list[i+1].T_t && list[i].T_t < float32(温度控制范围最高值) {
  612. lowPoint += 1
  613. }
  614. if lowPoint == 2 {
  615. 开始时间 = list[i].T_time
  616. break
  617. }
  618. }
  619. if len(开始时间) == 0 {
  620. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 开始时间 数据!"})
  621. return
  622. }
  623. type AVGClassList struct {
  624. T_sn string
  625. T_id string
  626. T_max float64
  627. T_min float64
  628. T_diff float64 // 最大最小值差异
  629. }
  630. fmt.Println("数据准备:", 开始时间, 结束时间, 温度控制范围最小值, 温度控制范围最高值)
  631. // -------------------- 温湿度绑定点vga_H --------------------
  632. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "--- 进行处理 数据!---"})
  633. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: fmt.Sprintf("开始时间:%s 结束时间:%s", 开始时间, 结束时间)})
  634. var AVGClassList_r []AVGClassList
  635. for _, i2 := range 部点终端_list {
  636. T_max := Task.Read_TaskData_max(T_task_id, i2.T_sn, i2.T_id, 开始时间, 结束时间)
  637. T_min := Task.Read_TaskData_min(T_task_id, i2.T_sn, i2.T_id, "", "")
  638. AVGClassList_r = append(AVGClassList_r, AVGClassList{T_sn: i2.T_sn, T_id: i2.T_id, T_max: T_max, T_min: T_min, T_diff: T_max - T_min})
  639. }
  640. for _, AVGClassList_i := range AVGClassList_r {
  641. if AVGClassList_i.T_max < 温度控制范围最高值 && AVGClassList_i.T_min > 温度控制范围最小值 {
  642. continue
  643. }
  644. var vgaca float64
  645. if (AVGClassList_i.T_max - AVGClassList_i.T_min) > (温度控制范围最高值 - 温度控制范围最小值 - 0.4) {
  646. // 压缩
  647. diff := RoundToDecimal(AVGClassList_i.T_max-AVGClassList_i.T_min, 1)
  648. // 获取压缩度
  649. compress := RoundToDecimal((温度控制范围最高值-温度控制范围最小值-0.6)/diff, 2)
  650. // 压缩
  651. Task.UpdateTaskDataTemperatureAndHumidityByGeometric(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", compress, 1)
  652. T_max_compress := RoundToDecimal(AVGClassList_i.T_max*compress, 1)
  653. T_min_compress := RoundToDecimal(AVGClassList_i.T_min*compress, 1)
  654. // 判断压缩后是否在 温度控制范围最小值-温度控制范围最高值范围内 不做处理
  655. if T_max_compress <= RoundToDecimal(温度控制范围最高值-0.1, 1) && T_min_compress >= RoundToDecimal(温度控制范围最小值+0.1, 1) {
  656. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + lib.To_string(AVGClassList_i.T_id) +
  657. " 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃ " +
  658. " 最小值:" + lib.To_string(AVGClassList_i.T_min) + "℃ " +
  659. " 压缩:" + lib.To_string(compress) +
  660. " 压缩后最大值:" + lib.To_string(T_max_compress) + "℃ " +
  661. " 压缩后最小值:" + lib.To_string(T_min_compress) + "℃ "})
  662. continue
  663. }
  664. // 压缩后仍高于 温度控制范围最高值,向下偏移
  665. if T_max_compress >= 温度控制范围最高值 {
  666. vgaca = RoundToDecimal(T_max_compress-温度控制范围最高值+0.1, 1)
  667. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + lib.To_string(AVGClassList_i.T_id) +
  668. " 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃ " +
  669. " 最小值:" + lib.To_string(AVGClassList_i.T_min) + "℃ " +
  670. " 压缩:" + lib.To_string(compress) +
  671. " 压缩后最大值:" + lib.To_string(AVGClassList_i.T_max*compress) + "℃ " +
  672. " 压缩后最小值:" + lib.To_string(AVGClassList_i.T_min*compress) + "℃ " +
  673. " 数据偏差:" + lib.To_string(vgaca) + "℃ " +
  674. " 向下偏移:" + lib.To_string(vgaca) + "℃ "})
  675. Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", -vgaca, 0)
  676. continue
  677. }
  678. // 压缩后仍低于 温度控制范围最小值,向上偏移
  679. if T_min_compress <= 温度控制范围最小值 {
  680. // 向上偏移
  681. vgaca = RoundToDecimal(温度控制范围最小值-AVGClassList_i.T_min*compress+0.1, 1)
  682. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + lib.To_string(AVGClassList_i.T_id) +
  683. " 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃ " +
  684. " 最小值:" + lib.To_string(AVGClassList_i.T_min) + "℃ " +
  685. " 压缩:" + lib.To_string(compress) +
  686. " 压缩后最大值:" + lib.To_string(AVGClassList_i.T_max*compress) + "℃ " +
  687. " 压缩后最小值:" + lib.To_string(AVGClassList_i.T_min*compress) + "℃ " +
  688. " 数据偏差:" + lib.To_string(vgaca) + "℃ " +
  689. " 向上偏移:" + lib.To_string(vgaca) + "℃ "})
  690. Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", vgaca, 0)
  691. }
  692. continue
  693. } else {
  694. // 向下偏移
  695. if AVGClassList_i.T_max >= 温度控制范围最高值 {
  696. vgaca = RoundToDecimal(AVGClassList_i.T_max-温度控制范围最高值+0.1, 1)
  697. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + lib.To_string(AVGClassList_i.T_id) +
  698. " 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃ " +
  699. " 最小值:" + lib.To_string(AVGClassList_i.T_min) + "℃ " +
  700. " 数据偏差:" + lib.To_string(vgaca) + "℃ " +
  701. " 向下偏移:" + lib.To_string(vgaca) + "℃ "})
  702. // 偏移
  703. Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", -vgaca, 0)
  704. continue
  705. }
  706. if AVGClassList_i.T_min <= 温度控制范围最小值 {
  707. vgaca = RoundToDecimal(温度控制范围最小值-AVGClassList_i.T_min+0.1, 1)
  708. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + lib.To_string(AVGClassList_i.T_id) +
  709. " 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃ " +
  710. " 最小值:" + lib.To_string(AVGClassList_i.T_min) + "℃ " +
  711. " 数据偏差: " + lib.To_string(vgaca) + "℃ " +
  712. " 向上偏移:" + lib.To_string(vgaca) + "℃ "})
  713. Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", vgaca, 0)
  714. }
  715. }
  716. }
  717. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "完成!"})
  718. // Close the connection
  719. c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
  720. }
  721. // 获取相邻2个终端值平均复制到
  722. func (c *TaskDataHandleController) SetAdjacentDeviceAVGTaskData(T_task_id string, device Device.DeviceClassList, StartTime, EndTime string) {
  723. DeviceClassListT_remark_r := Device.Read_DeviceClassList_List_id_T_remark(device.T_class, device.T_remark)
  724. // 分组统计每个sn的数据数量
  725. snList := Device.JoinDeviceClassListSnToString(DeviceClassListT_remark_r)
  726. TaskData_Total_GroupBySnId := Task.Read_TaskData_Total_GroupBySnId(T_task_id, snList, StartTime, EndTime)
  727. if len(TaskData_Total_GroupBySnId) < 2 {
  728. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "[" + device.T_remark + "]中没有找到 至少2条 可用数据"})
  729. return
  730. }
  731. // 获取 备注 下面关联设备,数量
  732. DeviceClassListT_remark_r_list_MAX := TaskData_Total_GroupBySnId[0].Total
  733. TaskData_Total_GroupBySnId_Map := make(map[string]int64)
  734. for _, v := range TaskData_Total_GroupBySnId {
  735. TaskData_Total_GroupBySnId_Map[v.T_sn] = v.Total
  736. }
  737. var completeDataDeviceClassList []Device.DeviceClassList
  738. for _, v := range DeviceClassListT_remark_r {
  739. if TaskData_Total_GroupBySnId_Map[v.T_sn] == DeviceClassListT_remark_r_list_MAX || v.T_sn == device.T_sn {
  740. completeDataDeviceClassList = append(completeDataDeviceClassList, v)
  741. }
  742. }
  743. if len(completeDataDeviceClassList) < 3 {
  744. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "[" + device.T_remark + "]中没有找到 至少2条 完整可用数据"})
  745. return
  746. }
  747. twoDevice := getBeforeAndAfter(device.T_id, completeDataDeviceClassList)
  748. sn1, id_str1 := twoDevice[0].T_sn, twoDevice[0].T_id
  749. sn2, id_str2 := twoDevice[1].T_sn, twoDevice[1].T_id
  750. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: device.T_sn + "|" + device.T_id + "开始平均复制到" +
  751. fmt.Sprintf("%s,%s|%s,%s", sn1, id_str1, sn2, id_str2)})
  752. List1, _ := Task.Read_TaskData_ById_List_AES(T_task_id, sn1, id_str1, StartTime, EndTime, 0, 9999)
  753. List2, _ := Task.Read_TaskData_ById_List_AES(T_task_id, sn2, id_str2, StartTime, EndTime, 0, 9999)
  754. num := len(List1)
  755. if len(List2) < len(List1) {
  756. num = len(List2)
  757. }
  758. if num == 0 {
  759. return
  760. }
  761. T_saveT := 60
  762. //var list []Task.TaskData_
  763. ct, _ := lib.TimeStrToTime(List1[0].T_time)
  764. var valueStrings []string
  765. for i := 0; i < num; i++ {
  766. if List1[i].T_time != List2[i].T_time {
  767. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: fmt.Sprintf("%s【%s】、%s【%s】时间不一致", List1[i].T_id, List1[i].T_time, List2[i].T_id, List2[i].T_time)})
  768. return
  769. }
  770. T_t := (List1[i].T_t + List2[i].T_t) / 2
  771. T_rh := (List1[i].T_rh + List2[i].T_rh) / 2
  772. valueStrings = append(valueStrings, fmt.Sprintf("('%s','%s',%v,%v,'%s')", device.T_sn, device.T_id, T_t, T_rh, ct.Format("2006-01-02 15:04:05")))
  773. ct = ct.Add(time.Second * time.Duration(T_saveT))
  774. }
  775. Task.DeleteTaskDataByTimeRange(T_task_id, device.T_sn, device.T_id, StartTime, EndTime)
  776. err := Task.Batch_Adds_TaskData(T_task_id, valueStrings)
  777. if err == nil {
  778. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: fmt.Sprintf("%d/%d", len(valueStrings), len(valueStrings))})
  779. }
  780. }
  781. func getBeforeAndAfter(T_id string, data []Device.DeviceClassList) []Device.DeviceClassList {
  782. var result []Device.DeviceClassList
  783. var index int
  784. for i, d := range data {
  785. if d.T_id == T_id {
  786. index = i
  787. break
  788. }
  789. }
  790. if index == 0 {
  791. result = append(result, data[len(data)-1], data[1])
  792. } else if index == len(data)-1 {
  793. result = append(result, data[len(data)-2], data[0])
  794. } else {
  795. result = append(result, data[index-1], data[index+1])
  796. }
  797. return result
  798. }
  799. func RoundToDecimal(num float64, decimal int) float64 {
  800. shift := math.Pow(10, float64(decimal))
  801. return math.Round(num*shift) / shift
  802. }