TaskHandle.go 81 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727
  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. "strconv"
  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. if Devicedata_list_MAX-cnt != 1 {
  100. // -----------开始平均复制到
  101. device := Device.DeviceClassList{
  102. T_class: DeviceClassList_r.T_class,
  103. T_id: DeviceClassList_r.T_id,
  104. T_sn: DeviceClassList_r.T_sn,
  105. T_remark: DeviceClassList_r.T_remark,
  106. }
  107. c.SetAdjacentDeviceAVGTaskData(T_task_id, device, "", "")
  108. // -----------开始平均复制到结束
  109. continue
  110. } else {
  111. if startTime != list[0].T_time {
  112. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: DeviceClassList_r.T_id + " 找到到自检时间点 " + startTime + " ~ " + list[0].T_time + " 开始自检"})
  113. Task.InsertTaskData(Task_r.T_task_id, Task.TaskData_{
  114. T_sn: list[0].T_sn,
  115. T_id: list[0].T_id,
  116. T_t: list[0].T_t,
  117. T_rh: list[0].T_rh,
  118. T_time: startTime,
  119. })
  120. continue
  121. }
  122. if endTime != list[len(list)-1].T_time {
  123. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: DeviceClassList_r.T_id + " 找到自检时间点 " + list[len(list)-1].T_time + " ~ " + endTime + " 开始自检"})
  124. Task.InsertTaskData(Task_r.T_task_id, Task.TaskData_{
  125. T_sn: list[len(list)-1].T_sn,
  126. T_id: list[len(list)-1].T_id,
  127. T_t: list[len(list)-1].T_t,
  128. T_rh: list[len(list)-1].T_rh,
  129. T_time: endTime,
  130. })
  131. continue
  132. }
  133. }
  134. }
  135. for i := 0; i < len(list)-1; i++ {
  136. current := list[i].T_time
  137. next := list[i+1].T_time
  138. ct, _ := time.Parse("2006-01-02 15:04:05", current)
  139. nt, _ := time.Parse("2006-01-02 15:04:05", next)
  140. interval := nt.Unix() - ct.Unix()
  141. //logs.Debug("时间间隔:", interval, "保存时间:", saveTime)
  142. //fmt.Println("当前:", current, "下一个:", next)
  143. // 缺一个时间点 补漏
  144. if int(interval) == 2*T_saveT {
  145. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: list[i].T_id + " 找到自检时间点 " + current + " ~ " + next + " 开始自检"})
  146. t := ct.Add(time.Second * time.Duration(T_saveT)).Format("2006-01-02 15:04") //时间临时变量
  147. ttt := (list[i].T_t + list[i+1].T_t) / 2
  148. trht := (list[i].T_rh + list[i+1].T_rh) / 2
  149. Task.InsertTaskData(Task_r.T_task_id, Task.TaskData_{
  150. T_sn: list[i].T_sn,
  151. T_id: list[i].T_id,
  152. T_t: ttt,
  153. T_rh: trht,
  154. T_time: t,
  155. })
  156. continue
  157. }
  158. // 缺的数据大于一个时间点,执行平均复制到
  159. if int(interval) > T_saveT {
  160. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: list[i].T_id + " 找到自检时间点 " + current + " ~ " + next + " 开始自检"})
  161. // -----------开始平均复制到
  162. device := Device.DeviceClassList{
  163. T_class: DeviceClassList_r.T_class,
  164. T_id: DeviceClassList_r.T_id,
  165. T_sn: DeviceClassList_r.T_sn,
  166. T_remark: DeviceClassList_r.T_remark,
  167. }
  168. c.SetAdjacentDeviceAVGTaskData(T_task_id, device, "", "")
  169. // -----------开始平均复制到结束
  170. // 平均复制结束,跳出循环
  171. break
  172. }
  173. }
  174. }
  175. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "完成!"})
  176. // Close the connection
  177. c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
  178. }
  179. // 数据持续时间 x 分钟 没有变化
  180. func (c *TaskDataHandleController) SSE_Continuously_unchanged_data() {
  181. T_task_id := c.GetString("T_task_id") // v26nplogbwt1
  182. T_timeout, _ := c.GetInt("T_timeout", 30) // 持续时间
  183. c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream")
  184. c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
  185. c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
  186. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "任务开始......"})
  187. Task_r, err := Task.Read_Task(T_task_id)
  188. if err != nil {
  189. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取任务信息失败!"})
  190. return
  191. }
  192. // 获取 备注 下面关联设备,数量
  193. DeviceClassList_list := Device.Read_DeviceClassList_List_id_By_Terminal(Task_r.T_class, false)
  194. // 选择 数据缺失的终端
  195. var DeleteDeviceClassList []Device.DeviceClassList
  196. for _, DeviceClassList_r := range DeviceClassList_list {
  197. TaskData_list, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, DeviceClassList_r.T_sn, DeviceClassList_r.T_id, "", "", 0, 9999)
  198. if len(TaskData_list) == 0 {
  199. continue
  200. }
  201. maxCount, start, end := Task.FindUnchangedInterval(TaskData_list)
  202. if strings.Contains(DeviceClassList_r.T_remark, "保温箱外环境测点") ||
  203. strings.Contains(DeviceClassList_r.T_remark, "冷藏库作业口外部环境测点") ||
  204. strings.Contains(DeviceClassList_r.T_remark, "冷藏库外部环境测点") ||
  205. strings.Contains(DeviceClassList_r.T_remark, "冷藏柜外部环境测点") ||
  206. strings.Contains(DeviceClassList_r.T_remark, "冷藏车外部环境测点") ||
  207. strings.Contains(DeviceClassList_r.T_remark, "仓库室外测点") {
  208. continue
  209. }
  210. if maxCount > T_timeout {
  211. Task.DeleteTaskDataByTimeRange(T_task_id, DeviceClassList_r.T_sn, DeviceClassList_r.T_id, "", "")
  212. DeleteDeviceClassList = append(DeleteDeviceClassList, DeviceClassList_r)
  213. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "找到" + DeviceClassList_r.T_id + " 探头, " +
  214. "最多连续 " + lib.To_string(maxCount) + " 分钟没有变化," +
  215. "开始时间:" + start + " 结束时间:" + end + "," +
  216. "开始自检"})
  217. }
  218. }
  219. for _, class_ := range DeleteDeviceClassList {
  220. // -----------开始平均复制到
  221. device := Device.DeviceClassList{
  222. T_class: class_.T_class,
  223. T_id: class_.T_id,
  224. T_sn: class_.T_sn,
  225. T_remark: class_.T_remark,
  226. }
  227. c.SetAdjacentDeviceAVGTaskData(T_task_id, device, "", "")
  228. // -----------开始平均复制到结束
  229. }
  230. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "完成!"})
  231. // Close the connection
  232. c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
  233. }
  234. // 区间数据校正 (布点区域数据自检) 均匀性布点,产品存放区域测点 区间数据超标校正 超标数据偏移到区间内
  235. func (c *TaskDataHandleController) SSE_Interval_data_correction() {
  236. T_task_id := c.GetString("T_task_id") // v26nplogbwt1
  237. c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream")
  238. c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
  239. c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
  240. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "任务开始......"})
  241. Task_r, err := Task.Read_Task(T_task_id)
  242. if err != nil {
  243. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取任务信息失败!"})
  244. return
  245. }
  246. 温度控制范围最小值 := float64(lib.To_float32(VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "温度控制范围最小值")))
  247. 温度控制范围最高值 := float64(lib.To_float32(VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "温度控制范围最高值")))
  248. if 温度控制范围最小值 == 0 || 温度控制范围最高值 == 0 {
  249. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温度控制范围 标签值不正确!"})
  250. return
  251. }
  252. // 均匀性布点 产品存放区域测点
  253. 部点终端_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "均匀性布点|产品存放区域测点|作业出入口总测点")
  254. if len(部点终端_list) <= 2 {
  255. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "均匀性布点|产品存放区域测点|作业出入口总测点 太少了,至少两条以上!"})
  256. return
  257. }
  258. 部点终端_sn_list := Device.JoinDeviceClassListSnToString(部点终端_list)
  259. var 开始时间, 结束时间, 趋势时间 string
  260. 开始时间, 结束时间, 趋势时间 = c.GetStartTimeAndEndTime(Task_r, 部点终端_sn_list, 温度控制范围最高值)
  261. if 开始时间 == "" || 结束时间 == "" {
  262. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 开始时间 或 结束时间 结束时间!"})
  263. return
  264. }
  265. type AVGClassList struct {
  266. T_sn string
  267. T_id string
  268. T_max float64
  269. T_min float64
  270. T_diff float64 // 最大最小值差异
  271. }
  272. fmt.Println("数据准备:", 开始时间, 结束时间, 温度控制范围最小值, 温度控制范围最高值)
  273. // -------------------- 温湿度绑定点vga_H --------------------
  274. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "--- 进行处理 数据!---"})
  275. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: fmt.Sprintf("开始时间:%s 结束时间:%s", 开始时间, 结束时间)})
  276. // 先整体向上偏移
  277. for _, i2 := range 部点终端_list {
  278. T_min := Task.Read_TaskData_min(T_task_id, i2.T_sn, i2.T_id, "", "")
  279. if T_min < RoundToDecimal(温度控制范围最小值+0.1, 1) {
  280. Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, i2.T_sn, i2.T_id, "", "", RoundToDecimal(温度控制范围最小值+0.1-T_min, 1), 0)
  281. }
  282. }
  283. // ----------获取保留数据------------
  284. var 开空开, 开空开驼峰结束时间, 保空开, 保空开驼峰结束时间 string
  285. var valueStrings1, valueStrings2, BWXValueStrings []string
  286. if Task_r.T_device_type != "X" {
  287. valueStrings1, valueStrings2, 开空开, 开空开驼峰结束时间, 保空开, 保空开驼峰结束时间 = c.GetRetainData(Task_r, 部点终端_sn_list)
  288. } else {
  289. BWXValueStrings = c.GetBWXRetainData(Task_r, 部点终端_sn_list, 结束时间, 趋势时间)
  290. }
  291. // ----------获取保留数据结束------------
  292. var AVGClassList_r []AVGClassList
  293. for _, i2 := range 部点终端_list {
  294. T_max := Task.Read_TaskData_max(T_task_id, i2.T_sn, i2.T_id, 开始时间, 结束时间)
  295. T_min := Task.Read_TaskData_min(T_task_id, i2.T_sn, i2.T_id, "", "")
  296. 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})
  297. }
  298. for _, AVGClassList_i := range AVGClassList_r {
  299. if AVGClassList_i.T_max < 温度控制范围最高值 && AVGClassList_i.T_min > 温度控制范围最小值 {
  300. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "测点 " + lib.To_string(AVGClassList_i.T_id) +
  301. " 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃ " +
  302. " 最小值:" + lib.To_string(AVGClassList_i.T_min) + "℃ " +
  303. " 符合要求!"})
  304. continue
  305. }
  306. var vgaca float64
  307. if RoundToDecimal(AVGClassList_i.T_max-AVGClassList_i.T_min, 1) > RoundToDecimal(温度控制范围最高值-温度控制范围最小值-0.4, 1) {
  308. // 压缩
  309. diff := RoundToDecimal(AVGClassList_i.T_max-AVGClassList_i.T_min, 1)
  310. // 获取压缩度
  311. compress := RoundToDecimal((温度控制范围最高值-温度控制范围最小值-0.6)/diff, 2)
  312. // 压缩
  313. Task.UpdateTaskDataTemperatureAndHumidityByGeometric(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", compress, 1)
  314. T_max_compress := RoundToDecimal(AVGClassList_i.T_max*compress, 1)
  315. T_min_compress := RoundToDecimal(AVGClassList_i.T_min*compress, 1)
  316. // 判断压缩后是否在 温度控制范围最小值-温度控制范围最高值范围内 不做处理
  317. if T_max_compress <= RoundToDecimal(温度控制范围最高值-0.1, 1) && T_min_compress >= RoundToDecimal(温度控制范围最小值+0.1, 1) {
  318. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + lib.To_string(AVGClassList_i.T_id) +
  319. " 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃ " +
  320. " 最小值:" + lib.To_string(AVGClassList_i.T_min) + "℃ " +
  321. " 压缩:" + lib.To_string(compress) +
  322. " 压缩后最大值:" + lib.To_string(T_max_compress) + "℃ " +
  323. " 压缩后最小值:" + lib.To_string(T_min_compress) + "℃ "})
  324. continue
  325. }
  326. // 压缩后仍高于 温度控制范围最高值,向下偏移
  327. if T_max_compress >= 温度控制范围最高值 {
  328. vgaca = RoundToDecimal(T_max_compress-温度控制范围最高值+0.1, 1)
  329. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + lib.To_string(AVGClassList_i.T_id) +
  330. " 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃ " +
  331. " 最小值:" + lib.To_string(AVGClassList_i.T_min) + "℃ " +
  332. " 压缩:" + lib.To_string(compress) +
  333. " 压缩后最大值:" + lib.To_string(RoundToDecimal(AVGClassList_i.T_max*compress, 1)) + "℃ " +
  334. " 压缩后最小值:" + lib.To_string(RoundToDecimal(AVGClassList_i.T_min*compress, 1)) + "℃ " +
  335. " 数据偏差:" + lib.To_string(vgaca) + "℃ " +
  336. " 向下偏移:" + lib.To_string(vgaca) + "℃ "})
  337. Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", -vgaca, 0)
  338. continue
  339. }
  340. // 压缩后仍低于 温度控制范围最小值,向上偏移
  341. if T_min_compress <= 温度控制范围最小值 {
  342. // 向上偏移
  343. vgaca = RoundToDecimal(温度控制范围最小值-AVGClassList_i.T_min*compress+0.1, 1)
  344. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + lib.To_string(AVGClassList_i.T_id) +
  345. " 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃ " +
  346. " 最小值:" + lib.To_string(AVGClassList_i.T_min) + "℃ " +
  347. " 压缩:" + lib.To_string(compress) +
  348. " 压缩后最大值:" + lib.To_string(RoundToDecimal(AVGClassList_i.T_max*compress, 1)) + "℃ " +
  349. " 压缩后最小值:" + lib.To_string(RoundToDecimal(AVGClassList_i.T_min*compress, 1)) + "℃ " +
  350. " 数据偏差:" + lib.To_string(vgaca) + "℃ " +
  351. " 向上偏移:" + lib.To_string(vgaca) + "℃ "})
  352. Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", vgaca, 0)
  353. }
  354. continue
  355. } else {
  356. // 向下偏移
  357. if AVGClassList_i.T_max >= 温度控制范围最高值 {
  358. vgaca = RoundToDecimal(AVGClassList_i.T_max-温度控制范围最高值+0.1, 1)
  359. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + lib.To_string(AVGClassList_i.T_id) +
  360. " 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃ " +
  361. " 最小值:" + lib.To_string(AVGClassList_i.T_min) + "℃ " +
  362. " 数据偏差:" + lib.To_string(vgaca) + "℃ " +
  363. " 向下偏移:" + lib.To_string(vgaca) + "℃ "})
  364. // 偏移
  365. Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", -vgaca, 0)
  366. continue
  367. }
  368. if AVGClassList_i.T_min <= 温度控制范围最小值 {
  369. vgaca = RoundToDecimal(温度控制范围最小值-AVGClassList_i.T_min+0.1, 1)
  370. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + lib.To_string(AVGClassList_i.T_id) +
  371. " 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃ " +
  372. " 最小值:" + lib.To_string(AVGClassList_i.T_min) + "℃ " +
  373. " 数据偏差: " + lib.To_string(vgaca) + "℃ " +
  374. " 向上偏移:" + lib.To_string(vgaca) + "℃ "})
  375. Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", vgaca, 0)
  376. }
  377. }
  378. }
  379. // ----------恢复保留数据------------
  380. if Task_r.T_device_type != "X" {
  381. c.SaveRetainData(Task_r, 部点终端_list, valueStrings1, valueStrings2, 开空开, 开空开驼峰结束时间, 保空开, 保空开驼峰结束时间)
  382. } else {
  383. c.SaveBWXRetainData(Task_r, 部点终端_list, BWXValueStrings, 结束时间, 趋势时间, 60)
  384. }
  385. // ----------恢复保留数据结束------------
  386. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "完成!"})
  387. // Close the connection
  388. c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
  389. }
  390. // 绑定点与终端比对 (绑定点数据自检) 终端数据为参照物,绑定点数据在终端偏差±1℃,保温箱为±0.5℃
  391. func (c *TaskDataHandleController) SSE_Comparison_between_binding_points_and_terminals() {
  392. T_task_id := c.GetString("T_task_id") // v26nplogbwt1
  393. T_deviation, _ := c.GetFloat("T_deviation", 1.0) // 误差绑定点数据与终端对比偏差
  394. c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream")
  395. c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
  396. c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
  397. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "任务开始......"})
  398. Task_r, err := Task.Read_Task(T_task_id)
  399. if err != nil {
  400. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取任务信息失败!"})
  401. return
  402. }
  403. // 保温箱偏差为0.5
  404. if Task_r.T_device_type == "X" {
  405. T_deviation = 0.5
  406. }
  407. // -------------------- 获取开始时间--------------------
  408. 温度控制范围最高值 := float64(lib.To_float32(VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "温度控制范围最高值")))
  409. if 温度控制范围最高值 == 0 {
  410. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温度控制范围最高值 标签值不正确!"})
  411. return
  412. }
  413. 温度控制范围最小值 := float64(lib.To_float32(VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "温度控制范围最小值")))
  414. if 温度控制范围最小值 == 0 {
  415. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温度控制范围最小值 标签值不正确!"})
  416. return
  417. }
  418. // 均匀性布点 产品存放区域测点
  419. 部点终端_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "均匀性布点|产品存放区域测点")
  420. if len(部点终端_list) <= 2 {
  421. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "均匀性布点,产品存放区域测点 太少了,至少两条以上!"})
  422. return
  423. }
  424. 部点终端_sn_list := Device.JoinDeviceClassListSnToString(部点终端_list)
  425. var 开始时间, 结束时间, 趋势时间 string
  426. 开始时间, 结束时间, 趋势时间 = c.GetStartTimeAndEndTime(Task_r, 部点终端_sn_list, 温度控制范围最高值)
  427. if 开始时间 == "" || 结束时间 == "" {
  428. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 开始时间 或 结束时间 结束时间!"})
  429. return
  430. }
  431. // ----------获取保留数据------------
  432. var 开空开, 开空开驼峰结束时间, 保空开, 保空开驼峰结束时间 string
  433. var valueStrings1, valueStrings2, BWXValueStrings []string
  434. if Task_r.T_device_type != "X" {
  435. valueStrings1, valueStrings2, 开空开, 开空开驼峰结束时间, 保空开, 保空开驼峰结束时间 = c.GetRetainData(Task_r, 部点终端_sn_list)
  436. } else {
  437. BWXValueStrings = c.GetBWXRetainData(Task_r, 部点终端_sn_list, 结束时间, 趋势时间)
  438. }
  439. // ----------获取保留数据结束------------
  440. 监测终端_list := Device.Read_DeviceClassList_List_id_By_Terminal(Task_r.T_class, true)
  441. if len(监测终端_list) < 1 {
  442. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 监测终端!"})
  443. return
  444. }
  445. 温湿度绑定点_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "温湿度绑定点")
  446. if len(温湿度绑定点_list) < 1 {
  447. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 温湿度绑定点!"})
  448. return
  449. }
  450. if len(监测终端_list) != len(温湿度绑定点_list) {
  451. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "监测终端 和 温湿度绑定点 数量不一致!"})
  452. return
  453. }
  454. var 监测终端01, 监测终端02, 温湿度绑定点1, 温湿度绑定点2 Device.DeviceClassList
  455. for _, list := range 监测终端_list {
  456. if strings.Contains(list.T_remark, "监测终端01") {
  457. 监测终端01 = list
  458. }
  459. if strings.Contains(list.T_remark, "监测终端02") {
  460. 监测终端02 = list
  461. }
  462. }
  463. for _, list := range 温湿度绑定点_list {
  464. if strings.Contains(list.T_remark, "温湿度绑定点1") {
  465. 温湿度绑定点1 = list
  466. }
  467. if strings.Contains(list.T_remark, "温湿度绑定点2") {
  468. 温湿度绑定点2 = list
  469. }
  470. }
  471. var 温湿度绑定点vga, 监测终端vga float64
  472. 温湿度绑定点vga = Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点1.T_sn, 温湿度绑定点1.T_id, 开始时间, 结束时间)
  473. if 温湿度绑定点vga == 0 {
  474. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温湿度绑定点1 无数据!请先处理数据!"})
  475. return
  476. }
  477. 监测终端vga = Task.Read_TaskData_AVG(T_task_id, 监测终端01.T_sn, 监测终端01.T_id, 开始时间, 结束时间)
  478. if 监测终端vga == 0 {
  479. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "监测终端01 无数据!请先处理数据!"})
  480. return
  481. }
  482. 温湿度绑定点vga = RoundToDecimal(温湿度绑定点vga, 1)
  483. 监测终端vga = RoundToDecimal(监测终端vga, 1)
  484. if len(监测终端_list) == 1 {
  485. // 只有一个终端,直接偏移到±T_deviation 区间内
  486. if (温湿度绑定点vga > 监测终端vga && 温湿度绑定点vga < 监测终端vga+T_deviation) || (温湿度绑定点vga < 监测终端vga && 温湿度绑定点vga > 监测终端vga-T_deviation) {
  487. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "" +
  488. "温湿度绑定点1平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " +
  489. "监测终端01 平均值" + lib.To_string(监测终端vga) + "℃ " +
  490. "数据偏差: " + lib.To_string(RoundToDecimal(监测终端vga-温湿度绑定点vga, 1)) + "℃ " +
  491. "设置:" + lib.To_string(T_deviation) + "℃" +
  492. "符合要求!"})
  493. }
  494. T_max := Task.Read_TaskData_max(T_task_id, 温湿度绑定点1.T_sn, 温湿度绑定点1.T_id, 开始时间, 结束时间)
  495. T_min := Task.Read_TaskData_min(T_task_id, 温湿度绑定点1.T_sn, 温湿度绑定点1.T_id, 开始时间, 结束时间)
  496. // 平均值向下偏移
  497. if 温湿度绑定点vga > RoundToDecimal(监测终端vga+T_deviation, 1) {
  498. c.SetAverageShiftedDownward(T_task_id, 温湿度绑定点1.T_id, T_deviation, 监测终端vga, 温湿度绑定点vga, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "")
  499. }
  500. // 平均值向上偏移
  501. if 温湿度绑定点vga < RoundToDecimal(监测终端vga-T_deviation, 1) {
  502. c.SetAverageShiftedUpward(T_task_id, 温湿度绑定点1.T_id, T_deviation, 监测终端vga, 温湿度绑定点vga, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "")
  503. }
  504. } else if len(监测终端_list) == 2 {
  505. // 有两个终端,找出目标温湿度绑定点vga, 目标温湿度绑定点2vga最优解后偏移
  506. var 温湿度绑定点2vga, 监测终端2vga float64
  507. 温湿度绑定点2vga = Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点2.T_sn, 温湿度绑定点2.T_id, 开始时间, 结束时间)
  508. if 温湿度绑定点2vga == 0 {
  509. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温湿度绑定点3 无数据!请先处理数据!"})
  510. }
  511. 监测终端2vga = Task.Read_TaskData_AVG(T_task_id, 监测终端02.T_sn, 监测终端02.T_id, 开始时间, 结束时间)
  512. if 监测终端2vga == 0 {
  513. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "监测终端02 无数据!请先处理数据!"})
  514. }
  515. 温湿度绑定点2vga = RoundToDecimal(温湿度绑定点2vga, 1)
  516. 监测终端2vga = RoundToDecimal(监测终端2vga, 1)
  517. if math.Abs(监测终端2vga-监测终端vga) > 3 {
  518. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "监测终端vga|监测终端2vga 绝对值相差超过3度,无法处理!"})
  519. return
  520. }
  521. // 获取监测终端和绑定点的平均值
  522. 目标温湿度绑定点vga, 目标温湿度绑定点2vga, isExist := findBindingPointsOptimalAdjustment(监测终端vga, 监测终端2vga, 温湿度绑定点vga, 温湿度绑定点2vga, T_deviation)
  523. if !isExist {
  524. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 最优 温湿度绑定点1|温湿度绑定点2| 调整值!"})
  525. return
  526. }
  527. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "监测终端01 平均值" + lib.To_string(监测终端vga) + "℃ " +
  528. "监测终端02 平均值" + lib.To_string(监测终端2vga) + "℃ " +
  529. "温湿度绑定点1 原始平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " +
  530. "温湿度绑定点2 原始平均值:" + lib.To_string(温湿度绑定点2vga) + "℃ " +
  531. "温湿度绑定点1 最优平均值:" + lib.To_string(目标温湿度绑定点vga) + "℃ " +
  532. "温湿度绑定点2 最优平均值:" + lib.To_string(目标温湿度绑定点2vga) + "℃ " +
  533. "设置:" + lib.To_string(T_deviation) + "℃"})
  534. if 目标温湿度绑定点vga != 温湿度绑定点vga {
  535. T_max := Task.Read_TaskData_max(T_task_id, 温湿度绑定点1.T_sn, 温湿度绑定点1.T_id, 开始时间, 结束时间)
  536. T_min := Task.Read_TaskData_min(T_task_id, 温湿度绑定点1.T_sn, 温湿度绑定点1.T_id, 开始时间, 结束时间)
  537. // 平均值向下偏移
  538. if 温湿度绑定点vga > RoundToDecimal(目标温湿度绑定点vga, 1) {
  539. c.SetAverageShiftedDownward(T_task_id, 温湿度绑定点1.T_id, 0, 目标温湿度绑定点vga, 温湿度绑定点vga, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "")
  540. }
  541. // 平均值向上偏移
  542. if 温湿度绑定点vga < RoundToDecimal(目标温湿度绑定点vga, 1) {
  543. c.SetAverageShiftedUpward(T_task_id, 温湿度绑定点1.T_id, 0, 目标温湿度绑定点vga, 温湿度绑定点vga, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "")
  544. }
  545. }
  546. if 目标温湿度绑定点2vga != 温湿度绑定点2vga {
  547. T_max := Task.Read_TaskData_max(T_task_id, 温湿度绑定点2.T_sn, 温湿度绑定点2.T_id, 开始时间, 结束时间)
  548. T_min := Task.Read_TaskData_min(T_task_id, 温湿度绑定点2.T_sn, 温湿度绑定点2.T_id, 开始时间, 结束时间)
  549. // 平均值向下偏移
  550. if 温湿度绑定点vga > RoundToDecimal(目标温湿度绑定点vga, 1) {
  551. c.SetAverageShiftedDownward(T_task_id, 温湿度绑定点2.T_id, 0, 目标温湿度绑定点vga, 温湿度绑定点vga, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "")
  552. }
  553. // 平均值向上偏移
  554. if 温湿度绑定点vga < RoundToDecimal(目标温湿度绑定点vga, 1) {
  555. c.SetAverageShiftedUpward(T_task_id, 温湿度绑定点2.T_id, 0, 目标温湿度绑定点vga, 温湿度绑定点vga, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "")
  556. }
  557. }
  558. }
  559. // ----------恢复保留数据------------
  560. if Task_r.T_device_type != "X" {
  561. c.SaveRetainData(Task_r, 部点终端_list, valueStrings1, valueStrings2, 开空开, 开空开驼峰结束时间, 保空开, 保空开驼峰结束时间)
  562. } else {
  563. c.SaveBWXRetainData(Task_r, 部点终端_list, BWXValueStrings, 结束时间, 趋势时间, 60)
  564. }
  565. // ----------恢复保留数据结束------------
  566. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "完成!"})
  567. // Close the connection
  568. c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
  569. }
  570. /*
  571. 绑定点与冷热点比对 (冷热点数据自检)绑定点数据为参照物,绑定点数据在终端偏差±1℃,保温箱为±0.5℃
  572. 固定偏移一固定值,降到超限的平均复制,仍然超限再压缩
  573. */
  574. func (c *TaskDataHandleController) SSE_Compare_binding_points_with_cold_and_hot_spots() {
  575. T_task_id := c.GetString("T_task_id") // v26nplogbwt1
  576. T_deviation, _ := c.GetFloat("T_deviation", 1.0) // 偏差时间
  577. c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream")
  578. c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
  579. c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
  580. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "任务开始......"})
  581. Task_r, err := Task.Read_Task(T_task_id)
  582. if err != nil {
  583. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取任务信息失败!"})
  584. return
  585. }
  586. // 保温箱偏差为0.5
  587. if Task_r.T_device_type == "X" {
  588. T_deviation = 0.5
  589. }
  590. 温度控制范围最高值 := float64(lib.To_float32(VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "温度控制范围最高值")))
  591. if 温度控制范围最高值 == 0 {
  592. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温度控制范围最高值 标签值不正确!"})
  593. return
  594. }
  595. 温度控制范围最小值 := float64(lib.To_float32(VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "温度控制范围最小值")))
  596. if 温度控制范围最小值 == 0 {
  597. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温度控制范围最小值 标签值不正确!"})
  598. return
  599. }
  600. // ------- 温湿度绑定点
  601. 温湿度绑定点1_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "温湿度绑定点1")
  602. if len(温湿度绑定点1_list) != 1 {
  603. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温湿度绑定点1 中找到 " + lib.To_string(len(温湿度绑定点1_list)) + "条,布点终端异常!"})
  604. return
  605. }
  606. 温湿度绑定点2_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "温湿度绑定点2")
  607. if len(温湿度绑定点2_list) != 1 {
  608. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "温湿度绑定点2 没找到,将 温湿度绑定点1 设置低点"})
  609. 温湿度绑定点2_list = 温湿度绑定点1_list
  610. }
  611. // 均匀性布点 产品存放区域测点
  612. 部点终端_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "均匀性布点|产品存放区域测点")
  613. if len(部点终端_list) == 0 {
  614. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "没有找到 均匀性布点,产品存放区域测点,作业出入口总测点 测点数据!"})
  615. return
  616. }
  617. 部点终端_sn_list := Device.JoinDeviceClassListSnToString(部点终端_list)
  618. var 开始时间, 结束时间, 趋势时间 string
  619. 开始时间, 结束时间, 趋势时间 = c.GetStartTimeAndEndTime(Task_r, 部点终端_sn_list, 温度控制范围最高值)
  620. if 开始时间 == "" || 结束时间 == "" {
  621. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 开始时间 或 结束时间 结束时间!"})
  622. return
  623. }
  624. // ----------获取保留数据------------
  625. var 开空开, 开空开驼峰结束时间, 保空开, 保空开驼峰结束时间 string
  626. var valueStrings1, valueStrings2, BWXValueStrings []string
  627. if Task_r.T_device_type != "X" {
  628. valueStrings1, valueStrings2, 开空开, 开空开驼峰结束时间, 保空开, 保空开驼峰结束时间 = c.GetRetainData(Task_r, 部点终端_sn_list)
  629. } else {
  630. BWXValueStrings = c.GetBWXRetainData(Task_r, 部点终端_sn_list, 结束时间, 趋势时间)
  631. }
  632. // ----------获取保留数据结束------------
  633. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "--- 开始时间--- " + 开始时间})
  634. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "--- 结束时间--- " + 结束时间})
  635. type AVGClassList struct {
  636. T_id string
  637. T_vga float64
  638. T_max float64
  639. T_min float64
  640. }
  641. 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), 开始时间, 结束时间)
  642. if len(TaskData_Total_GroupBySnId) == 0 {
  643. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温湿度绑定点 无数据"})
  644. return
  645. }
  646. for _, v := range TaskData_Total_GroupBySnId {
  647. if v.Total == 0 {
  648. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温湿度绑定点[" + v.T_id + "] 无数据"})
  649. return
  650. }
  651. }
  652. 温湿度绑定点1vga := Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点1_list[0].T_sn, 温湿度绑定点1_list[0].T_id, 开始时间, 结束时间)
  653. 温湿度绑定点2vga := Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点2_list[0].T_sn, 温湿度绑定点2_list[0].T_id, 开始时间, 结束时间)
  654. if 温湿度绑定点1vga == 温湿度绑定点2vga {
  655. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "温湿度绑定点1 与 温湿度绑定点2 平均值相等,将 进行上下偏移处理!"})
  656. 温湿度绑定点1vga += T_deviation / 2
  657. 温湿度绑定点2vga -= T_deviation / 2
  658. T_deviation /= 2
  659. }
  660. var 温湿度绑定点vga_H, 温湿度绑定点vga_L AVGClassList
  661. if 温湿度绑定点1vga > 温湿度绑定点2vga {
  662. 温湿度绑定点vga_H.T_id = 温湿度绑定点1_list[0].T_id
  663. 温湿度绑定点vga_H.T_vga = RoundToDecimal(温湿度绑定点1vga, 1)
  664. 温湿度绑定点vga_L.T_id = 温湿度绑定点2_list[0].T_id
  665. 温湿度绑定点vga_L.T_vga = RoundToDecimal(温湿度绑定点2vga, 1)
  666. } else {
  667. 温湿度绑定点vga_L.T_id = 温湿度绑定点1_list[0].T_id
  668. 温湿度绑定点vga_L.T_vga = RoundToDecimal(温湿度绑定点1vga, 1)
  669. 温湿度绑定点vga_H.T_id = 温湿度绑定点2_list[0].T_id
  670. 温湿度绑定点vga_H.T_vga = RoundToDecimal(温湿度绑定点2vga, 1)
  671. }
  672. fmt.Println("温湿度绑定点:", 温湿度绑定点vga_H, 温湿度绑定点vga_L)
  673. var Average_H_List []Task.TaskData_Average // 热点
  674. var Average_L_List []Task.TaskData_Average // 冷点
  675. snList := Device.JoinDeviceClassListSnToString(部点终端_list)
  676. TaskData_Average_GroupBySnId := Task.Read_TaskData_Average_GroupBySnId(Task_r.T_task_id, snList, 开始时间, 结束时间)
  677. if len(TaskData_Average_GroupBySnId) < 2 {
  678. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "未找到 均匀性布点,产品存放区域测点 数据冷热点,平均值数据少于2条!"})
  679. return
  680. }
  681. for _, average := range TaskData_Average_GroupBySnId {
  682. if RoundToDecimal(average.Average, 1) > RoundToDecimal(温湿度绑定点vga_H.T_vga+T_deviation, 1) {
  683. average.Average = RoundToDecimal(average.Average, 1)
  684. Average_H_List = append(Average_H_List, average)
  685. }
  686. if RoundToDecimal(average.Average, 1) < RoundToDecimal(温湿度绑定点vga_L.T_vga-T_deviation, 1) {
  687. average.Average = RoundToDecimal(average.Average, 1)
  688. Average_L_List = append(Average_L_List, average)
  689. }
  690. }
  691. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "------ 进行 高点处理 ------"})
  692. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "------ 高点平均值 " + lib.To_string(温湿度绑定点vga_H.T_vga) + "------"})
  693. if len(Average_H_List) == 0 {
  694. Average_H := TaskData_Average_GroupBySnId[0]
  695. // 高点不在冷热点范围
  696. if RoundToDecimal(Average_H.Average, 1) < RoundToDecimal(温湿度绑定点vga_H.T_vga-T_deviation, 1) &&
  697. RoundToDecimal(Average_H.Average, 1) > RoundToDecimal(温湿度绑定点vga_L.T_vga+T_deviation, 1) {
  698. // 热点向上偏移到高点-T_deviation
  699. T_max := Task.Read_TaskData_max(T_task_id, Average_H.T_sn, Average_H.T_id, 开始时间, 结束时间)
  700. T_min := Task.Read_TaskData_min(T_task_id, Average_H.T_sn, Average_H.T_id, 开始时间, 结束时间)
  701. c.SetAverageShiftedUpward(T_task_id, Average_H.T_id, T_deviation, 温湿度绑定点vga_H.T_vga, Average_H.Average, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "")
  702. }
  703. } else {
  704. for _, Average_H := range Average_H_List {
  705. // 热点向下偏移到高点范围
  706. T_max := Task.Read_TaskData_max(T_task_id, Average_H.T_sn, Average_H.T_id, 开始时间, 结束时间)
  707. T_min := Task.Read_TaskData_min(T_task_id, Average_H.T_sn, Average_H.T_id, 开始时间, 结束时间)
  708. c.SetAverageShiftedDownward(T_task_id, Average_H.T_id, T_deviation, 温湿度绑定点vga_H.T_vga, Average_H.Average, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "")
  709. }
  710. }
  711. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "------ 进行 低点处理 ------"})
  712. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "------ 低点平均值 " + lib.To_string(温湿度绑定点vga_L.T_vga) + "------"})
  713. if len(Average_L_List) == 0 {
  714. Average_L := TaskData_Average_GroupBySnId[0]
  715. // 冷点不在冷热点范围
  716. if RoundToDecimal(Average_L.Average, 1) < RoundToDecimal(温湿度绑定点vga_L.T_vga+T_deviation, 1) &&
  717. RoundToDecimal(Average_L.Average, 1) < RoundToDecimal(温湿度绑定点vga_L.T_vga-T_deviation, 1) {
  718. // 热点向下偏移到高点范围
  719. T_max := Task.Read_TaskData_max(T_task_id, Average_L.T_sn, Average_L.T_id, 开始时间, 结束时间)
  720. T_min := Task.Read_TaskData_min(T_task_id, Average_L.T_sn, Average_L.T_id, 开始时间, 结束时间)
  721. c.SetAverageShiftedDownward(T_task_id, Average_L.T_id, T_deviation, 温湿度绑定点vga_H.T_vga, Average_L.Average, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "")
  722. }
  723. } else {
  724. for _, Average_L := range Average_L_List {
  725. // 热点向下偏移到高点范围
  726. T_max := Task.Read_TaskData_max(T_task_id, Average_L.T_sn, Average_L.T_id, 开始时间, 结束时间)
  727. T_min := Task.Read_TaskData_min(T_task_id, Average_L.T_sn, Average_L.T_id, 开始时间, 结束时间)
  728. c.SetAverageShiftedUpward(T_task_id, Average_L.T_id, T_deviation, 温湿度绑定点vga_L.T_vga, Average_L.Average, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "")
  729. }
  730. }
  731. // ----------恢复保留数据------------
  732. if Task_r.T_device_type != "X" {
  733. c.SaveRetainData(Task_r, 部点终端_list, valueStrings1, valueStrings2, 开空开, 开空开驼峰结束时间, 保空开, 保空开驼峰结束时间)
  734. } else {
  735. c.SaveBWXRetainData(Task_r, 部点终端_list, BWXValueStrings, 结束时间, 趋势时间, 60)
  736. }
  737. // ----------恢复保留数据结束------------
  738. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "完成!"})
  739. // Close the connection
  740. c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
  741. }
  742. // 获取相邻2个终端值平均复制到
  743. func (c *TaskDataHandleController) SetAdjacentDeviceAVGTaskData(T_task_id string, device Device.DeviceClassList, StartTime, EndTime string) {
  744. DeviceClassListT_remark_r := Device.Read_DeviceClassList_List_id_T_remark(device.T_class, device.T_remark)
  745. // 分组统计每个sn的数据数量
  746. snList := Device.JoinDeviceClassListSnToString(DeviceClassListT_remark_r)
  747. TaskData_Total_GroupBySnId := Task.Read_TaskData_Total_GroupBySnId(T_task_id, snList, StartTime, EndTime)
  748. if len(TaskData_Total_GroupBySnId) < 2 {
  749. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "[" + device.T_remark + "]中没有找到 至少2条 可用数据"})
  750. return
  751. }
  752. // 获取 备注 下面关联设备,数量
  753. DeviceClassListT_remark_r_list_MAX := TaskData_Total_GroupBySnId[0].Total
  754. TaskData_Total_GroupBySnId_Map := make(map[string]int64)
  755. for _, v := range TaskData_Total_GroupBySnId {
  756. TaskData_Total_GroupBySnId_Map[v.T_sn] = v.Total
  757. }
  758. var completeDataDeviceClassList []Device.DeviceClassList
  759. for _, v := range DeviceClassListT_remark_r {
  760. if TaskData_Total_GroupBySnId_Map[v.T_sn] == DeviceClassListT_remark_r_list_MAX || v.T_sn == device.T_sn {
  761. completeDataDeviceClassList = append(completeDataDeviceClassList, v)
  762. }
  763. }
  764. if len(completeDataDeviceClassList) < 3 {
  765. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "[" + device.T_remark + "]中没有找到 至少2条 完整可用数据"})
  766. return
  767. }
  768. twoDevice := getBeforeAndAfter(device.T_id, completeDataDeviceClassList)
  769. sn1, id_str1 := twoDevice[0].T_sn, twoDevice[0].T_id
  770. sn2, id_str2 := twoDevice[1].T_sn, twoDevice[1].T_id
  771. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: device.T_sn + "," + device.T_id + "开始平均复制到" +
  772. fmt.Sprintf("%s,%s|%s,%s", sn1, id_str1, sn2, id_str2)})
  773. List1, _ := Task.Read_TaskData_ById_List_AES(T_task_id, sn1, id_str1, StartTime, EndTime, 0, 9999)
  774. List2, _ := Task.Read_TaskData_ById_List_AES(T_task_id, sn2, id_str2, StartTime, EndTime, 0, 9999)
  775. num := len(List1)
  776. if len(List2) < len(List1) {
  777. num = len(List2)
  778. }
  779. if num == 0 {
  780. return
  781. }
  782. T_saveT := 60
  783. //var list []Task.TaskData_
  784. ct, _ := lib.TimeStrToTime(List1[0].T_time)
  785. var valueStrings []string
  786. for i := 0; i < num; i++ {
  787. if List1[i].T_time != List2[i].T_time {
  788. 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)})
  789. return
  790. }
  791. T_t := (List1[i].T_t + List2[i].T_t) / 2
  792. T_rh := (List1[i].T_rh + List2[i].T_rh) / 2
  793. 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")))
  794. ct = ct.Add(time.Second * time.Duration(T_saveT))
  795. }
  796. Task.DeleteTaskDataByTimeRange(T_task_id, device.T_sn, device.T_id, StartTime, EndTime)
  797. err := Task.Batch_Adds_TaskData(T_task_id, valueStrings)
  798. if err == nil {
  799. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: fmt.Sprintf("%d/%d", len(valueStrings), len(valueStrings))})
  800. }
  801. }
  802. func getBeforeAndAfter(T_id string, data []Device.DeviceClassList) []Device.DeviceClassList {
  803. var result []Device.DeviceClassList
  804. var index int
  805. for i, d := range data {
  806. if d.T_id == T_id {
  807. index = i
  808. break
  809. }
  810. }
  811. if index == 0 {
  812. result = append(result, data[len(data)-1], data[1])
  813. } else if index == len(data)-1 {
  814. result = append(result, data[len(data)-2], data[0])
  815. } else {
  816. result = append(result, data[index-1], data[index+1])
  817. }
  818. return result
  819. }
  820. func RoundToDecimal(num float64, decimal int) float64 {
  821. shift := math.Pow(10, float64(decimal))
  822. return math.Round(num*shift) / shift
  823. }
  824. /*
  825. 数据自检名称:平均值数据自检
  826. 测点:柜内所有测点|箱内所有测点|均匀性布点和产品存放区域测点、温湿度绑定点01、温湿度绑定点02
  827. 时间:采用“绑定点数据自检”的时间
  828. 策略:先执行完成“绑定点数据自检”后,温湿度绑定点01和温湿度绑定点02的数据就作为基准数据不变,温湿度绑定点01平均值与柜内所有测点平均值之间的差异在±0.5℃范围以内,温湿度绑定点02平均值与柜内所有测点平均值之间的差异在±0.5℃范围以内,若柜内所有测点的平均值较大或较小,则对柜内所有测点中平均值较大或较小的测点曲线进行偏移调整,使柜内所有测点的平均值靠近温湿度绑定点的平均值,从而达到绑定点与柜内所有测点的平均值差异在±0.5℃。以上“柜内所有测点”要分别换成“箱内所有测点”、“均匀性布点和产品存放区域测点”;“平均值数据自检”和“冷热点数据自检”可以同时勾选(冷库和冷车会用到)进行自检也可以单独执行(冷柜和保温箱只执行“平均值数据自检”)
  829. */
  830. func (c *TaskDataHandleController) SSE_Compare_binding_points_with_Average() {
  831. T_task_id := c.GetString("T_task_id") // v26nplogbwt1
  832. T_deviation := 0.5 // 偏差时间
  833. c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream")
  834. c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
  835. c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
  836. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "任务开始......"})
  837. Task_r, err := Task.Read_Task(T_task_id)
  838. if err != nil {
  839. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取任务信息失败!"})
  840. return
  841. }
  842. // 保温箱偏差为0.5
  843. if Task_r.T_device_type == "X" {
  844. T_deviation = 0.5
  845. }
  846. 温度控制范围最高值 := float64(lib.To_float32(VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "温度控制范围最高值")))
  847. if 温度控制范围最高值 == 0 {
  848. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温度控制范围最高值 标签值不正确!"})
  849. return
  850. }
  851. 温度控制范围最小值 := float64(lib.To_float32(VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "温度控制范围最小值")))
  852. if 温度控制范围最小值 == 0 {
  853. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温度控制范围最小值 标签值不正确!"})
  854. return
  855. }
  856. // 均匀性布点 产品存放区域测点
  857. 部点终端_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "均匀性布点|柜内所有测点|箱内所有测点|产品存放区域测点")
  858. 部点终端_sn_list := Device.JoinDeviceClassListSnToString(部点终端_list)
  859. var 开始时间, 结束时间, 趋势时间 string
  860. 开始时间, 结束时间, 趋势时间 = c.GetStartTimeAndEndTime(Task_r, 部点终端_sn_list, 温度控制范围最高值)
  861. if 开始时间 == "" || 结束时间 == "" {
  862. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 开始时间 或 结束时间 结束时间!"})
  863. return
  864. }
  865. // ----------获取保留数据------------
  866. var 开空开, 开空开驼峰结束时间, 保空开, 保空开驼峰结束时间 string
  867. var valueStrings1, valueStrings2, BWXValueStrings []string
  868. if Task_r.T_device_type != "X" {
  869. valueStrings1, valueStrings2, 开空开, 开空开驼峰结束时间, 保空开, 保空开驼峰结束时间 = c.GetRetainData(Task_r, 部点终端_sn_list)
  870. } else {
  871. BWXValueStrings = c.GetBWXRetainData(Task_r, 部点终端_sn_list, 结束时间, 趋势时间)
  872. }
  873. // ----------获取保留数据结束------------
  874. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "--- 开始时间--- " + 开始时间})
  875. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "--- 结束时间--- " + 结束时间})
  876. if len(部点终端_list) == 0 {
  877. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "没有找到 柜内所有测点|箱内所有测点|均匀性布点|产品存放区域测点 测点数据!"})
  878. return
  879. }
  880. snList := Device.JoinDeviceClassListSnToString(部点终端_list)
  881. originalAvg := Task.Read_TaskData_Average(Task_r.T_task_id, snList, 开始时间, 结束时间)
  882. originalAvg = RoundToDecimal(originalAvg, 1)
  883. 温湿度绑定点_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "温湿度绑定点")
  884. if len(温湿度绑定点_list) < 1 {
  885. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 温湿度绑定点!"})
  886. return
  887. }
  888. var 温湿度绑定点1, 温湿度绑定点2 Device.DeviceClassList
  889. for _, list := range 温湿度绑定点_list {
  890. if strings.Contains(list.T_remark, "温湿度绑定点1") {
  891. 温湿度绑定点1 = list
  892. }
  893. if strings.Contains(list.T_remark, "温湿度绑定点2") {
  894. 温湿度绑定点2 = list
  895. }
  896. }
  897. 温湿度绑定点vga := Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点1.T_sn, 温湿度绑定点1.T_id, 开始时间, 结束时间)
  898. if 温湿度绑定点vga == 0 {
  899. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温湿度绑定点1 无数据!请先处理数据!"})
  900. return
  901. }
  902. if len(温湿度绑定点_list) == 1 {
  903. 温湿度绑定点vga = RoundToDecimal(温湿度绑定点vga, 1)
  904. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "------ 进行 柜内所有测点|箱内所有测点|均匀性布点|产品存放区域测点 平均值处理 ------"})
  905. if (originalAvg >= 温湿度绑定点vga && originalAvg <= 温湿度绑定点vga+T_deviation) || (originalAvg <= 温湿度绑定点vga && originalAvg >= 温湿度绑定点vga-T_deviation) {
  906. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "" +
  907. "温湿度绑定点1 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " +
  908. "测点 平均值" + lib.To_string(originalAvg) + "℃ " +
  909. "数据偏差: " + lib.To_string(RoundToDecimal(math.Abs(originalAvg-温湿度绑定点vga), 1)) + "℃ " +
  910. "设置:" + lib.To_string(T_deviation) + "℃" +
  911. "符合要求!"})
  912. } else {
  913. // 平均值最低点向上偏移
  914. if originalAvg < 温湿度绑定点vga-T_deviation {
  915. for originalAvg < 温湿度绑定点vga-T_deviation {
  916. TaskData_Average_GroupBySnId := Task.Read_TaskData_Average_GroupBySnId(Task_r.T_task_id, snList, 开始时间, 结束时间)
  917. if len(TaskData_Average_GroupBySnId) == 0 {
  918. break
  919. }
  920. Average_L := TaskData_Average_GroupBySnId[len(TaskData_Average_GroupBySnId)-1]
  921. T_max := Task.Read_TaskData_max(T_task_id, Average_L.T_sn, Average_L.T_id, 开始时间, 结束时间)
  922. T_min := Task.Read_TaskData_min(T_task_id, Average_L.T_sn, Average_L.T_id, 开始时间, 结束时间)
  923. c.SetAverageShiftedUpward(T_task_id, Average_L.T_id, T_deviation, RoundToDecimal(Average_L.Average+0.1, 1), Average_L.Average, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "")
  924. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "" +
  925. "温湿度绑定点1 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " +
  926. "测点 平均值" + lib.To_string(originalAvg) + "℃ " +
  927. "数据偏差: " + lib.To_string(math.Abs(originalAvg-温湿度绑定点vga)) + "℃ " +
  928. "设置:" + lib.To_string(T_deviation) + "℃" +
  929. "向上偏移0.1℃"})
  930. originalAvg = Task.Read_TaskData_Average(Task_r.T_task_id, snList, 开始时间, 结束时间)
  931. originalAvg = RoundToDecimal(originalAvg, 1)
  932. }
  933. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "" +
  934. "温湿度绑定点1 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " +
  935. "测点 平均值" + lib.To_string(originalAvg) + "℃ " +
  936. "数据偏差: " + lib.To_string(RoundToDecimal(math.Abs(originalAvg-温湿度绑定点vga), 1)) + "℃ " +
  937. "设置:" + lib.To_string(T_deviation) + "℃" +
  938. "符合要求!"})
  939. }
  940. // 向下偏移
  941. if originalAvg > 温湿度绑定点vga+T_deviation {
  942. for originalAvg > 温湿度绑定点vga+T_deviation {
  943. // 热点向下偏移到高点范围
  944. TaskData_Average_GroupBySnId := Task.Read_TaskData_Average_GroupBySnId(Task_r.T_task_id, snList, 开始时间, 结束时间)
  945. if len(TaskData_Average_GroupBySnId) == 0 {
  946. break
  947. }
  948. Average_H := TaskData_Average_GroupBySnId[0]
  949. T_max := Task.Read_TaskData_max(T_task_id, Average_H.T_sn, Average_H.T_id, 开始时间, 结束时间)
  950. T_min := Task.Read_TaskData_min(T_task_id, Average_H.T_sn, Average_H.T_id, 开始时间, 结束时间)
  951. c.SetAverageShiftedDownward(T_task_id, Average_H.T_id, T_deviation, RoundToDecimal(Average_H.Average-0.1, 1), Average_H.Average, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "")
  952. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "" +
  953. "温湿度绑定点1 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " +
  954. "测点 平均值" + lib.To_string(originalAvg) + "℃ " +
  955. "数据偏差: " + lib.To_string(RoundToDecimal(math.Abs(originalAvg-温湿度绑定点vga), 1)) + "℃ " +
  956. "设置:" + lib.To_string(T_deviation) + "℃" +
  957. "向下偏移0.1℃"})
  958. originalAvg = Task.Read_TaskData_Average(Task_r.T_task_id, snList, 开始时间, 结束时间)
  959. originalAvg = RoundToDecimal(originalAvg, 1)
  960. }
  961. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "" +
  962. "温湿度绑定点1 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " +
  963. "测点 平均值" + lib.To_string(originalAvg) + "℃ " +
  964. "数据偏差: " + lib.To_string(RoundToDecimal(math.Abs(originalAvg-温湿度绑定点vga), 1)) + "℃ " +
  965. "设置:" + lib.To_string(T_deviation) + "℃" +
  966. "符合要求!"})
  967. }
  968. }
  969. } else if len(温湿度绑定点_list) == 2 {
  970. 温湿度绑定点2vga := Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点2.T_sn, 温湿度绑定点2.T_id, 开始时间, 结束时间)
  971. if 温湿度绑定点2vga == 0 {
  972. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温湿度绑定点2 无数据!请先处理数据!"})
  973. return
  974. }
  975. // 获取最优平均值
  976. 目标originalAvg := findAverageOptimalAdjustment(温湿度绑定点vga, 温湿度绑定点2vga, originalAvg)
  977. 目标originalAvg = RoundToDecimal(目标originalAvg, 1)
  978. if 目标originalAvg != originalAvg {
  979. // 平均值最低点向上偏移
  980. if originalAvg < 目标originalAvg {
  981. for originalAvg < 目标originalAvg {
  982. TaskData_Average_GroupBySnId := Task.Read_TaskData_Average_GroupBySnId(Task_r.T_task_id, snList, 开始时间, 结束时间)
  983. if len(TaskData_Average_GroupBySnId) == 0 {
  984. break
  985. }
  986. Average_L := TaskData_Average_GroupBySnId[len(TaskData_Average_GroupBySnId)-1]
  987. T_max := Task.Read_TaskData_max(T_task_id, Average_L.T_sn, Average_L.T_id, 开始时间, 结束时间)
  988. T_min := Task.Read_TaskData_min(T_task_id, Average_L.T_sn, Average_L.T_id, 开始时间, 结束时间)
  989. c.SetAverageShiftedUpward(T_task_id, Average_L.T_id, T_deviation, RoundToDecimal(Average_L.Average+0.1, 1), Average_L.Average, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "")
  990. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "" +
  991. " 温湿度绑定点1 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " +
  992. " 温湿度绑定点2 平均值:" + lib.To_string(温湿度绑定点2vga) + "℃ " +
  993. " 测点 平均值" + lib.To_string(originalAvg) + "℃ " +
  994. " 测点 最优平均值" + lib.To_string(目标originalAvg) + "℃ " +
  995. " 数据偏差: " + lib.To_string(math.Abs(originalAvg-目标originalAvg)) + "℃ " +
  996. " 设置:" + lib.To_string(T_deviation) + "℃" +
  997. " 冷点:" + Average_L.T_id +
  998. " 向上偏移0.1℃"})
  999. originalAvg = Task.Read_TaskData_Average(Task_r.T_task_id, snList, 开始时间, 结束时间)
  1000. originalAvg = RoundToDecimal(originalAvg, 1)
  1001. }
  1002. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "" +
  1003. " 温湿度绑定点1 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " +
  1004. " 温湿度绑定点2 平均值:" + lib.To_string(温湿度绑定点2vga) + "℃ " +
  1005. " 测点 平均值" + lib.To_string(originalAvg) + "℃ " +
  1006. " 测点 最优平均值" + lib.To_string(目标originalAvg) + "℃ " +
  1007. " 数据偏差: " + lib.To_string(RoundToDecimal(math.Abs(originalAvg-温湿度绑定点vga), 1)) + "℃ " +
  1008. " 设置:" + lib.To_string(T_deviation) + "℃" +
  1009. " 符合要求!"})
  1010. }
  1011. // 向下偏移
  1012. if originalAvg > 目标originalAvg {
  1013. for originalAvg > 目标originalAvg {
  1014. // 热点向下偏移到高点范围
  1015. TaskData_Average_GroupBySnId := Task.Read_TaskData_Average_GroupBySnId(Task_r.T_task_id, snList, 开始时间, 结束时间)
  1016. if len(TaskData_Average_GroupBySnId) == 0 {
  1017. break
  1018. }
  1019. Average_H := TaskData_Average_GroupBySnId[0]
  1020. T_max := Task.Read_TaskData_max(T_task_id, Average_H.T_sn, Average_H.T_id, 开始时间, 结束时间)
  1021. T_min := Task.Read_TaskData_min(T_task_id, Average_H.T_sn, Average_H.T_id, 开始时间, 结束时间)
  1022. c.SetAverageShiftedDownward(T_task_id, Average_H.T_id, T_deviation, RoundToDecimal(Average_H.Average-0.1, 1), Average_H.Average, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "")
  1023. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "" +
  1024. " 温湿度绑定点1 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " +
  1025. " 温湿度绑定点2 平均值:" + lib.To_string(温湿度绑定点2vga) + "℃ " +
  1026. " 测点 平均值" + lib.To_string(originalAvg) + "℃ " +
  1027. " 测点 最优平均值" + lib.To_string(目标originalAvg) + "℃ " +
  1028. " 数据偏差: " + lib.To_string(math.Abs(originalAvg-目标originalAvg)) + "℃ " +
  1029. " 设置:" + lib.To_string(T_deviation) + "℃" +
  1030. " 冷点:" + Average_H.T_id +
  1031. " 向下偏移0.1℃"})
  1032. originalAvg = Task.Read_TaskData_Average(Task_r.T_task_id, snList, 开始时间, 结束时间)
  1033. originalAvg = RoundToDecimal(originalAvg, 1)
  1034. }
  1035. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "" +
  1036. " 温湿度绑定点1 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " +
  1037. " 温湿度绑定点2 平均值:" + lib.To_string(温湿度绑定点2vga) + "℃ " +
  1038. " 测点 平均值" + lib.To_string(originalAvg) + "℃ " +
  1039. " 数据偏差: " + lib.To_string(RoundToDecimal(math.Abs(originalAvg-目标originalAvg), 1)) + "℃ " +
  1040. " 设置:" + lib.To_string(T_deviation) + "℃" +
  1041. " 符合要求!"})
  1042. }
  1043. }
  1044. }
  1045. // 温控传感器绑定点 与 柜内所有测点|箱内所有测点|均匀性布点和产品存放区域测点 对比 ±1
  1046. T_deviation = 1
  1047. 温控传感器绑定点_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "温控传感器绑定点1|温控传感器绑定点2")
  1048. if len(温控传感器绑定点_list) == 0 {
  1049. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "没有找到温控传感器绑定点!"})
  1050. return
  1051. }
  1052. for i, classList := range 温控传感器绑定点_list {
  1053. 温控传感器绑定点OriginalAvg := Task.Read_TaskData_Average(Task_r.T_task_id, classList.T_sn, 开始时间, 结束时间)
  1054. 温控传感器绑定点OriginalAvg = RoundToDecimal(温控传感器绑定点OriginalAvg, 1)
  1055. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "------ 进行 温控传感器绑定点" + strconv.Itoa(i+1) + " 平均值处理 ------"})
  1056. if (温控传感器绑定点OriginalAvg >= originalAvg && 温控传感器绑定点OriginalAvg <= originalAvg+T_deviation) || (温控传感器绑定点OriginalAvg <= originalAvg && 温控传感器绑定点OriginalAvg >= originalAvg-T_deviation) {
  1057. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: " 温控传感器绑定点" + lib.To_string(i+1) + " 平均值:" + lib.To_string(温控传感器绑定点OriginalAvg) + "℃ " +
  1058. " 测点平均值" + lib.To_string(originalAvg) + "℃ " +
  1059. " 数据偏差: " + lib.To_string(RoundToDecimal(math.Abs(温控传感器绑定点OriginalAvg-originalAvg), 1)) + "℃ " +
  1060. " 设置:" + lib.To_string(T_deviation) + "℃" +
  1061. " 符合要求!"})
  1062. } else {
  1063. // 平均值最低点向上偏移
  1064. if 温控传感器绑定点OriginalAvg < originalAvg-T_deviation {
  1065. for 温控传感器绑定点OriginalAvg < originalAvg-T_deviation {
  1066. T_max := Task.Read_TaskData_max(T_task_id, classList.T_sn, classList.T_id, 开始时间, 结束时间)
  1067. T_min := Task.Read_TaskData_min(T_task_id, classList.T_sn, classList.T_id, 开始时间, 结束时间)
  1068. c.SetAverageShiftedUpward(T_task_id, classList.T_id, T_deviation, RoundToDecimal(温控传感器绑定点OriginalAvg+0.1, 1), 温控传感器绑定点OriginalAvg, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "")
  1069. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "温控传感器绑定点" + lib.To_string(i+1) + " 平均值:" + lib.To_string(温控传感器绑定点OriginalAvg) + "℃ " +
  1070. "测点平均值" + lib.To_string(originalAvg) + "℃ " +
  1071. "数据偏差: " + lib.To_string(RoundToDecimal(math.Abs(温控传感器绑定点OriginalAvg-originalAvg), 1)) + "℃ " +
  1072. "设置:" + lib.To_string(T_deviation) + "℃" +
  1073. "平均值向上偏移:0.1℃"})
  1074. 温控传感器绑定点OriginalAvg = Task.Read_TaskData_Average(Task_r.T_task_id, classList.T_sn, 开始时间, 结束时间)
  1075. 温控传感器绑定点OriginalAvg = RoundToDecimal(温控传感器绑定点OriginalAvg, 1)
  1076. }
  1077. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "温控传感器绑定点" + lib.To_string(i+1) + " 平均值:" + lib.To_string(温控传感器绑定点OriginalAvg) + "℃ " +
  1078. "测点平均值" + lib.To_string(originalAvg) + "℃ " +
  1079. "数据偏差: " + lib.To_string(RoundToDecimal(math.Abs(温控传感器绑定点OriginalAvg-originalAvg), 1)) + "℃ " +
  1080. "设置:" + lib.To_string(T_deviation) + "℃" +
  1081. "符合要求"})
  1082. continue
  1083. }
  1084. // 向下偏移
  1085. if 温控传感器绑定点OriginalAvg > originalAvg+T_deviation {
  1086. for 温控传感器绑定点OriginalAvg > originalAvg+T_deviation {
  1087. // 热点向下偏移到高点范围
  1088. T_max := Task.Read_TaskData_max(T_task_id, classList.T_sn, classList.T_id, 开始时间, 结束时间)
  1089. T_min := Task.Read_TaskData_min(T_task_id, classList.T_sn, classList.T_id, 开始时间, 结束时间)
  1090. c.SetAverageShiftedDownward(T_task_id, classList.T_id, T_deviation, RoundToDecimal(温控传感器绑定点OriginalAvg-0.1, 1), 温控传感器绑定点OriginalAvg, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "")
  1091. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "温控传感器绑定点" + lib.To_string(i+1) + " 平均值:" + lib.To_string(温控传感器绑定点OriginalAvg) + "℃ " +
  1092. "测点平均值" + lib.To_string(originalAvg) + "℃ " +
  1093. "数据偏差: " + lib.To_string(RoundToDecimal(math.Abs(温控传感器绑定点OriginalAvg-originalAvg), 1)) + "℃ " +
  1094. "设置:" + lib.To_string(T_deviation) + "℃" +
  1095. "平均值向下偏移:0.1℃"})
  1096. 温控传感器绑定点OriginalAvg = Task.Read_TaskData_Average(Task_r.T_task_id, classList.T_sn, 开始时间, 结束时间)
  1097. 温控传感器绑定点OriginalAvg = RoundToDecimal(温控传感器绑定点OriginalAvg, 1)
  1098. }
  1099. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "温控传感器绑定点" + lib.To_string(i+1) + " 平均值:" + lib.To_string(温控传感器绑定点OriginalAvg) + "℃ " +
  1100. "测点平均值" + lib.To_string(originalAvg) + "℃ " +
  1101. "数据偏差: " + lib.To_string(RoundToDecimal(math.Abs(温控传感器绑定点OriginalAvg-originalAvg), 1)) + "℃ " +
  1102. "设置:" + lib.To_string(T_deviation) + "℃" +
  1103. "符合要求"})
  1104. }
  1105. }
  1106. }
  1107. // ----------恢复保留数据------------
  1108. if Task_r.T_device_type != "X" {
  1109. c.SaveRetainData(Task_r, 部点终端_list, valueStrings1, valueStrings2, 开空开, 开空开驼峰结束时间, 保空开, 保空开驼峰结束时间)
  1110. } else {
  1111. c.SaveBWXRetainData(Task_r, 部点终端_list, BWXValueStrings, 结束时间, 趋势时间, 60)
  1112. }
  1113. // ----------恢复保留数据结束------------
  1114. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "完成!"})
  1115. // Close the connection
  1116. c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
  1117. }
  1118. /*
  1119. 平均值下移
  1120. targetAvg 参考平均值
  1121. originalAvg 原始平均值
  1122. T_min 整段数据最小值
  1123. T_max 整段数据最大值
  1124. minLimit 温度控制范围最小值
  1125. maxLimit 温度控制范围最大值
  1126. */
  1127. func (c *TaskDataHandleController) SetAverageShiftedDownward(T_task_id, T_id string, T_deviation, targetAvg, originalAvg, T_min, T_max, minLimit, maxLimit float64, StartTime, EndTime string) {
  1128. 目标avg := RoundToDecimal(targetAvg+T_deviation, 1)
  1129. vgaca := RoundToDecimal(originalAvg-目标avg, 1)
  1130. //向下偏移后整段数据最小值大于温度控制范围最小值
  1131. if RoundToDecimal(T_min-vgaca, 1) > RoundToDecimal(minLimit, 1) && RoundToDecimal(T_max-vgaca, 1) < RoundToDecimal(maxLimit, 1) {
  1132. Task.UpdateTaskDataTemperatureAndHumidityByGeometricAVG(T_task_id, T_id, "", "", -vgaca)
  1133. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" +
  1134. " 测点 " + lib.To_string(T_id) +
  1135. " 最大值:" + lib.To_string(T_max) + "℃ " +
  1136. " 最小值:" + lib.To_string(T_min) + "℃ " +
  1137. " 参考平均值:" + lib.To_string(RoundToDecimal(targetAvg, 1)) + "℃ " +
  1138. " 原始平均值:" + lib.To_string(RoundToDecimal(originalAvg, 1)) + "℃ " +
  1139. " 数据偏差:" + lib.To_string(vgaca) + "℃ " +
  1140. " 向下偏移:" + lib.To_string(vgaca) + "℃ "})
  1141. } else {
  1142. compress1 := RoundToDecimal((minLimit+0.3-目标avg)/(T_min-originalAvg), 1)
  1143. compress2 := RoundToDecimal((maxLimit-0.3-目标avg)/(T_max-originalAvg), 1)
  1144. compress := math.Min(compress1, compress2)
  1145. if RoundToDecimal(T_max*compress, 1) < maxLimit && RoundToDecimal(T_min*compress, 1) > minLimit {
  1146. vgaca = 0
  1147. } else {
  1148. vgaca = RoundToDecimal(目标avg-compress*originalAvg, 1)
  1149. }
  1150. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" +
  1151. " 测点" + lib.To_string(T_id) +
  1152. " 最大值:" + lib.To_string(T_max) + "℃ " +
  1153. " 最小值:" + lib.To_string(T_min) + "℃ " +
  1154. " 参考平均值:" + lib.To_string(RoundToDecimal(targetAvg, 1)) + "℃ " +
  1155. " 原始平均值:" + lib.To_string(RoundToDecimal(originalAvg, 1)) + "℃ " +
  1156. " 缩放:" + lib.To_string(compress) +
  1157. " 缩放后最大值:" + lib.To_string(RoundToDecimal(T_max*compress, 1)) + "℃ " +
  1158. " 缩放后最小值:" + lib.To_string(RoundToDecimal(T_min*compress, 1)) + "℃ " +
  1159. " 数据偏差:" + lib.To_string(vgaca) + "℃ " +
  1160. " 偏移:" + lib.To_string(vgaca) + "℃ "})
  1161. // 压缩
  1162. Task.UpdateTaskDataTemperatureAndHumidityByGeometric_id(T_task_id, T_id, "", "", compress)
  1163. // 偏移
  1164. if vgaca != 0 {
  1165. Task.UpdateTaskDataTemperatureAndHumidityByGeometricAVG(T_task_id, T_id, "", "", vgaca)
  1166. }
  1167. }
  1168. }
  1169. /*
  1170. 平均值上移
  1171. targetAvg 参考平均值
  1172. originalAvg 原始平均值
  1173. T_min 整段数据最小值
  1174. T_max 整段数据最大值
  1175. minLimit 温度控制范围最小值
  1176. maxLimit 温度控制范围最大值
  1177. */
  1178. func (c *TaskDataHandleController) SetAverageShiftedUpward(T_task_id, T_id string, T_deviation, targetAvg, originalAvg, T_min, T_max, minLimit, maxLimit float64, StartTime, EndTime string) {
  1179. 目标avg := RoundToDecimal(targetAvg-T_deviation, 1)
  1180. vgaca := RoundToDecimal(目标avg-originalAvg, 1)
  1181. if RoundToDecimal(T_max+vgaca, 1) < RoundToDecimal(maxLimit, 1) && RoundToDecimal(T_min+vgaca, 1) > RoundToDecimal(minLimit, 1) {
  1182. Task.UpdateTaskDataTemperatureAndHumidityByGeometricAVG(T_task_id, T_id, "", "", vgaca)
  1183. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" +
  1184. " 测点 " + lib.To_string(T_id) +
  1185. " 最大值:" + lib.To_string(T_max) + "℃ " +
  1186. " 最小值:" + lib.To_string(T_min) + "℃ " +
  1187. " 参考平均值:" + lib.To_string(RoundToDecimal(targetAvg, 1)) + "℃ " +
  1188. " 原始平均值:" + lib.To_string(RoundToDecimal(originalAvg, 1)) + "℃ " +
  1189. " 数据偏差:" + lib.To_string(vgaca) + "℃ " +
  1190. " 向上偏移:" + lib.To_string(vgaca) + "℃ "})
  1191. } else {
  1192. compress1 := RoundToDecimal((minLimit+0.3-目标avg)/(T_min-originalAvg), 1)
  1193. compress2 := RoundToDecimal((maxLimit-0.3-目标avg)/(T_max-originalAvg), 1)
  1194. compress := math.Min(compress1, compress2)
  1195. if RoundToDecimal(T_max*compress, 1) < maxLimit && RoundToDecimal(T_min*compress, 1) > minLimit {
  1196. vgaca = 0
  1197. } else {
  1198. vgaca = RoundToDecimal(目标avg-compress*originalAvg, 1)
  1199. }
  1200. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" +
  1201. " 测点" + lib.To_string(T_id) +
  1202. " 最大值:" + lib.To_string(T_max) + "℃ " +
  1203. " 最小值:" + lib.To_string(T_min) + "℃ " +
  1204. " 参考平均值:" + lib.To_string(RoundToDecimal(targetAvg, 1)) + "℃ " +
  1205. " 原始平均值:" + lib.To_string(RoundToDecimal(originalAvg, 1)) + "℃ " +
  1206. " 缩放:" + lib.To_string(compress) +
  1207. " 缩放后最大值:" + lib.To_string(RoundToDecimal(T_max*compress, 1)) + "℃ " +
  1208. " 缩放后最小值:" + lib.To_string(RoundToDecimal(T_min*compress, 1)) + "℃ " +
  1209. " 数据偏差:" + lib.To_string(vgaca) + "℃ " +
  1210. " 偏移:" + lib.To_string(vgaca) + "℃ "})
  1211. // 压缩
  1212. Task.UpdateTaskDataTemperatureAndHumidityByGeometric_id(T_task_id, T_id, "", "", compress)
  1213. // 偏移
  1214. if vgaca != 0 {
  1215. Task.UpdateTaskDataTemperatureAndHumidityByGeometricAVG(T_task_id, T_id, "", "", vgaca)
  1216. }
  1217. }
  1218. }
  1219. func (c *TaskDataHandleController) GetMetadata(T_task_id, SN, startTime string) (valueStrings []string, endTime string) {
  1220. list := Task.Read_TaskData_ById_AVG(T_task_id, SN, startTime, "")
  1221. // 获取第一个驼峰结束时间点
  1222. CalculateHumps_list := Task.CalculateHumpsByThreeDots(list)
  1223. if len(CalculateHumps_list) < 1 {
  1224. return
  1225. }
  1226. endTime = CalculateHumps_list[0].End.T_time
  1227. data1, _ := Task.Read_TaskData_ById_List_AES(T_task_id, SN, "", startTime, endTime, 0, 9999)
  1228. for _, v := range data1 {
  1229. valueStrings = append(valueStrings, fmt.Sprintf("('%s','%s',%v,%v,'%s')", v.T_sn, v.T_id, v.T_t, v.T_rh, v.T_time))
  1230. }
  1231. return valueStrings, endTime
  1232. }
  1233. // 获取保留数据
  1234. func (c *TaskDataHandleController) GetRetainData(Task_r Task.Task, SN string) (valueStrings1, valueStrings2 []string,
  1235. kkkStartTime, kkkEndTime, bkkStartTime, bkkEndTime string) {
  1236. var 开空开, 保空开, 开空开驼峰结束时间, 保空开驼峰结束时间 string
  1237. if Task_r.T_device_type != "X" {
  1238. 开空开 = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "开空开")
  1239. if len(开空开) == 0 {
  1240. 开空开 = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "开满开")
  1241. }
  1242. if len(开空开) == 0 {
  1243. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 开空开/开满开 时间 标签!"})
  1244. return
  1245. }
  1246. 保空开 = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "保空开")
  1247. if len(保空开) == 0 {
  1248. 保空开 = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "保满开")
  1249. }
  1250. if len(保空开) == 0 {
  1251. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 保空开/保满开 时间 标签!"})
  1252. return
  1253. }
  1254. valueStrings1, 开空开驼峰结束时间 = c.GetMetadata(Task_r.T_task_id, SN, 开空开)
  1255. valueStrings2, 保空开驼峰结束时间 = c.GetMetadata(Task_r.T_task_id, SN, 保空开)
  1256. }
  1257. return valueStrings1, valueStrings2, 开空开, 开空开驼峰结束时间, 保空开, 保空开驼峰结束时间
  1258. }
  1259. // 获取保留数据
  1260. func (c *TaskDataHandleController) SaveRetainData(Task_r Task.Task, SN_list []Device.DeviceClassList, valueStrings1, valueStrings2 []string,
  1261. kkkStartTime, kkkEndTime, bkkStartTime, bkkEndTime string) {
  1262. var err error
  1263. if len(valueStrings1) > 0 {
  1264. //将开空开/开满开时间开始第一个驼峰 写入原始数据
  1265. for _, device := range SN_list {
  1266. Task.DeleteTaskDataByTimeRange(Task_r.T_task_id, device.T_sn, device.T_id, kkkStartTime, kkkEndTime)
  1267. }
  1268. err = Task.Batch_Adds_TaskData(Task_r.T_task_id, valueStrings1)
  1269. if err == nil {
  1270. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: fmt.Sprintf("恢复开空开/开满开时间点后驼峰 %s ~ %s 数据 %d/%d", kkkStartTime, kkkEndTime, len(valueStrings1), len(valueStrings1))})
  1271. }
  1272. }
  1273. if len(valueStrings2) > 0 {
  1274. //将开空开/开满开时间开始第一个驼峰 写入原始数据
  1275. for _, device := range SN_list {
  1276. Task.DeleteTaskDataByTimeRange(Task_r.T_task_id, device.T_sn, device.T_id, bkkStartTime, bkkEndTime)
  1277. }
  1278. err = Task.Batch_Adds_TaskData(Task_r.T_task_id, valueStrings2)
  1279. if err == nil {
  1280. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: fmt.Sprintf("恢复保空开/保满开时间点后驼峰 %s ~ %s 数据 %d/%d", bkkStartTime, bkkEndTime, len(valueStrings2), len(valueStrings2))})
  1281. }
  1282. }
  1283. }
  1284. func (c *TaskDataHandleController) GetBWXRetainData(Task_r Task.Task, SN string, endTime, trendTime string) (BWXValueStrings []string) {
  1285. if endTime != trendTime {
  1286. data1, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, SN, "", trendTime, "", 0, 9999)
  1287. for _, v := range data1 {
  1288. BWXValueStrings = append(BWXValueStrings, fmt.Sprintf("('%s','%s',%v,%v,'%s')", v.T_sn, v.T_id, v.T_t, v.T_rh, v.T_time))
  1289. }
  1290. }
  1291. return
  1292. }
  1293. func (c *TaskDataHandleController) SaveBWXRetainData(Task_r Task.Task, SN_list []Device.DeviceClassList, BWXValueStrings []string, endTime, trendTime string, saveTime int) {
  1294. var err error
  1295. if endTime != trendTime && len(BWXValueStrings) > 0 {
  1296. //将开空开/开满开时间开始第一个驼峰 写入原始数据
  1297. for _, device := range SN_list {
  1298. Task.DeleteTaskDataByTimeRange(Task_r.T_task_id, device.T_sn, device.T_id, trendTime, "")
  1299. }
  1300. err = Task.Batch_Adds_TaskData(Task_r.T_task_id, BWXValueStrings)
  1301. if err == nil {
  1302. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: fmt.Sprintf("恢复 保温箱 原始数据 %d/%d", len(BWXValueStrings), len(BWXValueStrings))})
  1303. }
  1304. var startTime string
  1305. startTime = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "静态开箱作业开箱结束时间")
  1306. if len(startTime) == 0 {
  1307. startTime = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "动态开箱作业开箱结束时间")
  1308. }
  1309. if len(startTime) == 0 {
  1310. startTime = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "开箱作业开箱结束时间")
  1311. }
  1312. if len(startTime) == 0 {
  1313. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 静态开箱作业开箱结束时间|动态开箱作业开箱结束时间|开箱作业开箱结束时间 失败"})
  1314. return
  1315. }
  1316. startTimeT, _ := lib.TimeStrToTime(startTime)
  1317. startTime = startTimeT.Add(30 * time.Minute).Format("2006-01-02 15:04")
  1318. // 执行数据平滑
  1319. for _, v := range SN_list {
  1320. sn := v.T_sn
  1321. id_str := v.T_id
  1322. list, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, sn, id_str, startTime, trendTime, 0, 9999)
  1323. first := list[0]
  1324. last := list[len(list)-1]
  1325. current, _ := time.Parse("2006-01-02 15:04", first.T_time)
  1326. next, _ := time.Parse("2006-01-02 15:04", last.T_time)
  1327. interval := next.Sub(current).Seconds() / float64(saveTime)
  1328. ttInterval := (last.T_t - first.T_t) / float32(interval)
  1329. trhInterval := (last.T_rh - first.T_rh) / float32(interval)
  1330. tt := first.T_t
  1331. ttrh := first.T_rh
  1332. var valueStrings []string
  1333. for current.Unix() < next.Unix() {
  1334. tt += ttInterval
  1335. ttrh += trhInterval
  1336. ttime := current.Format("2006-01-02 15:04")
  1337. valueStrings = append(valueStrings, fmt.Sprintf("('%s','%s',%v,%v,'%s')", first.T_sn, id_str, tt, ttrh, ttime))
  1338. current = current.Add(time.Second * time.Duration(saveTime))
  1339. }
  1340. Task.DeleteTaskDataByTimeRange(Task_r.T_task_id, sn, id_str, startTime, trendTime)
  1341. err = Task.Batch_Adds_TaskData(Task_r.T_task_id, valueStrings)
  1342. if err == nil {
  1343. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: fmt.Sprintf("保温箱数据趋势 %d/%d", len(valueStrings), len(valueStrings))})
  1344. }
  1345. }
  1346. }
  1347. }
  1348. // 获取开始结束时间
  1349. func (c *TaskDataHandleController) GetStartTimeAndEndTime(Task_r Task.Task, SN string, maxLimit float64) (startTime, endTime, trendTime string) {
  1350. // 开始时间 获取温度下降到第二个低点时间
  1351. // 1. 获取温度平均值
  1352. list := Task.Read_TaskData_ById_AVG(Task_r.T_task_id, SN, "", "")
  1353. if len(list) < 2 {
  1354. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "均匀性布点+产品存放区域测点+作业出入口总测点 数据平均值 少于2条!"})
  1355. return
  1356. }
  1357. // 找平均值低于温度控制范围最高值的第二个最低点
  1358. lowPoint := 0
  1359. for i := 1; i <= len(list)-2; i++ {
  1360. if list[i].T_t < list[i-1].T_t && list[i].T_t < list[i+1].T_t && list[i].T_t < float32(maxLimit) {
  1361. lowPoint += 1
  1362. }
  1363. if lowPoint == 2 {
  1364. startTime = list[i].T_time
  1365. break
  1366. }
  1367. }
  1368. // 保温箱没有开空开,开满开
  1369. // 结束时间温度超限取没有超限时间点,结束时间温度未超限取最后一个时间点
  1370. if Task_r.T_device_type == "X" {
  1371. list2 := Task.Read_TaskData_ById_AVG_DESC(Task_r.T_task_id, SN, "", "")
  1372. if len(list) == 0 {
  1373. return
  1374. }
  1375. if float64(list2[0].T_t) < maxLimit {
  1376. endTime = list2[0].T_time
  1377. trendTime = list2[0].T_time
  1378. return
  1379. }
  1380. for i, avg := range list2 {
  1381. if RoundToDecimal(float64(avg.T_t), 1) < maxLimit {
  1382. endTime = avg.T_time
  1383. trendTime = list2[i-1].T_time
  1384. break
  1385. }
  1386. }
  1387. } else {
  1388. endTime = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "开空开")
  1389. if len(endTime) == 0 {
  1390. endTime = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "开满开")
  1391. }
  1392. if len(endTime) == 0 {
  1393. endTime = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "现场测试结束时间")
  1394. }
  1395. if len(endTime) == 0 {
  1396. return
  1397. }
  1398. }
  1399. return
  1400. }
  1401. /*
  1402. 计算绑定点的值
  1403. A 监测终端01平均值
  1404. B 监测终端02平均值
  1405. C 温湿度绑定点01平均值
  1406. D 温湿度绑定点02平均值
  1407. */
  1408. func findBindingPointsOptimalAdjustment(A, B, C, D, T_deviation float64) (float64, float64, bool) {
  1409. type DataPair struct {
  1410. A1 float64
  1411. B1 float64
  1412. }
  1413. T_deviation_half := 0.1
  1414. var dataPairs []DataPair
  1415. var A1, B1 float64 = -100, -100
  1416. // 生成A1和B1的可能值
  1417. for a1 := A - T_deviation; a1 <= A+T_deviation; a1 += T_deviation_half {
  1418. for b1 := B - T_deviation; b1 <= B+T_deviation; b1 += T_deviation_half {
  1419. // 检查是否存在满足条件的C值
  1420. minC := math.Max(a1-T_deviation_half, b1-T_deviation_half)
  1421. maxC := math.Min(a1+T_deviation_half, b1+T_deviation_half)
  1422. if minC <= maxC {
  1423. dataPairs = append(dataPairs, DataPair{A1: a1, B1: b1})
  1424. }
  1425. }
  1426. }
  1427. if len(dataPairs) == 1 {
  1428. A1 = dataPairs[0].A1
  1429. B1 = dataPairs[0].B1
  1430. }
  1431. if len(dataPairs) > 1 {
  1432. // 寻找最优解
  1433. minAdjustment := math.MaxFloat64
  1434. var optimalPair DataPair
  1435. for _, pair := range dataPairs {
  1436. adjustment := math.Abs(pair.A1-C) + math.Abs(pair.B1-D)
  1437. if adjustment < minAdjustment {
  1438. minAdjustment = adjustment
  1439. optimalPair = pair
  1440. }
  1441. }
  1442. A1 = optimalPair.A1
  1443. B1 = optimalPair.B1
  1444. }
  1445. if A1 == -100 || B1 == -100 {
  1446. return A1, B1, false
  1447. }
  1448. return A1, B1, true
  1449. }
  1450. /*
  1451. 计算绑定点的值
  1452. A 温湿度绑定点1平均值
  1453. B 温湿度绑定点2平均值
  1454. C 测点平均值
  1455. */
  1456. func findAverageOptimalAdjustment(A, B, C float64) float64 {
  1457. // 计算有效区间
  1458. minA := A - 0.5
  1459. maxA := A + 0.5
  1460. minB := B - 0.5
  1461. maxB := B + 0.5
  1462. // 求交集范围
  1463. lowerBound := math.Max(minA, minB)
  1464. upperBound := math.Min(maxA, maxB)
  1465. // 确定最优调整值
  1466. var optimalC float64
  1467. if C < lowerBound {
  1468. optimalC = lowerBound // 取区间下限
  1469. } else if C > upperBound {
  1470. optimalC = upperBound // 取区间上限
  1471. } else {
  1472. optimalC = C // 已在区间内无需调整
  1473. }
  1474. return optimalC
  1475. }