TaskHandle.go 96 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138
  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. "errors"
  9. "fmt"
  10. beego "github.com/beego/beego/v2/server/web"
  11. "math"
  12. "net/http"
  13. "strconv"
  14. "strings"
  15. "time"
  16. )
  17. type TaskDataHandleController struct {
  18. beego.Controller
  19. }
  20. /*
  21. 同区域数据缺失
  22. */
  23. // 测点自检 自动添加缺失终端,取关联绑定终端平均复制
  24. func (c *TaskDataHandleController) SSE_Automatically_add_missing_terminal() {
  25. T_task_id := c.GetString("T_task_id") // v26nplogbwt1
  26. println("T_task_id:", T_task_id)
  27. c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream")
  28. c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
  29. c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
  30. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "任务开始......"})
  31. Task_r, err := Task.Read_Task(T_task_id)
  32. if err != nil {
  33. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取任务信息失败!"})
  34. return
  35. }
  36. DeviceClassList_r := Device.Read_DeviceClassList_List_id_By_Terminal(Task_r.T_class, false)
  37. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "终端总共:" + lib.To_string(len(DeviceClassList_r)) + " 正在检查自检探头..."})
  38. for _, class_ := range DeviceClassList_r {
  39. _, cnt := Task.Read_TaskData_ById_List(Task_r.T_task_id, class_.T_sn, class_.T_id, "", "", 0, 1)
  40. if cnt == 0 {
  41. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "找到" + class_.T_id + " " + class_.T_remark + " 自检探头"})
  42. // -----------开始平均复制到
  43. device := Device.DeviceClassList{
  44. T_class: class_.T_class,
  45. T_id: class_.T_id,
  46. T_sn: class_.T_sn,
  47. T_remark: class_.T_remark,
  48. }
  49. c.SetAdjacentDeviceAVGTaskData(T_task_id, device, "", "")
  50. // -----------开始平均复制到结束
  51. }
  52. }
  53. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "完成!"})
  54. // Close the connection
  55. c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
  56. }
  57. // 测点数据自检 自动添加缺失数据,取关联绑定终端平均复制
  58. func (c *TaskDataHandleController) SSE_Automatically_add_missing_data() {
  59. T_task_id := c.GetString("T_task_id") // v26nplogbwt1
  60. c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream")
  61. c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
  62. c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
  63. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "任务开始......"})
  64. Task_r, err := Task.Read_Task(T_task_id)
  65. if err != nil {
  66. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取任务信息失败!"})
  67. return
  68. }
  69. // 时间间隔 s
  70. T_saveT := 60
  71. DeviceClassList_list := Device.Read_DeviceClassList_List_id_By_Terminal(Task_r.T_class, false)
  72. // 分组统计每个sn的数据数量
  73. snList := Device.JoinDeviceClassListSnToString(DeviceClassList_list)
  74. TaskData_Total_GroupBySnId := Task.Read_TaskData_Total_GroupBySnId(Task_r.T_task_id, snList, "", "")
  75. if len(TaskData_Total_GroupBySnId) == 0 {
  76. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "暂无测点需要自检!"})
  77. }
  78. Devicedata_list_MAX := TaskData_Total_GroupBySnId[0].Total
  79. TaskData_Total_GroupBySnId_Map := make(map[string]int64)
  80. for _, v := range TaskData_Total_GroupBySnId {
  81. TaskData_Total_GroupBySnId_Map[v.T_sn] = v.Total
  82. }
  83. 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, "", "")
  84. logs.Println("数据标准数量:", Devicedata_list_MAX)
  85. // 选择 数据缺失的终端
  86. for _, DeviceClassList_r := range DeviceClassList_list {
  87. total, ok := TaskData_Total_GroupBySnId_Map[DeviceClassList_r.T_sn]
  88. if !ok {
  89. // 测点自检事再处理
  90. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: DeviceClassList_r.T_id + " 终端自检数据 , 测点缺失,跳过"})
  91. continue
  92. }
  93. if Devicedata_list_MAX == total {
  94. continue
  95. }
  96. list, cnt := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, DeviceClassList_r.T_sn, DeviceClassList_r.T_id, "", "", 0, 9999)
  97. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: DeviceClassList_r.T_id + " 终端自检数据 ,数据差值:" + lib.To_string(Devicedata_list_MAX-cnt) + " "})
  98. // 开始结束时间不同,直接执行平均复制到
  99. if startTime != list[0].T_time || endTime != list[len(list)-1].T_time {
  100. if Devicedata_list_MAX-cnt != 1 {
  101. // -----------开始平均复制到
  102. device := Device.DeviceClassList{
  103. T_class: DeviceClassList_r.T_class,
  104. T_id: DeviceClassList_r.T_id,
  105. T_sn: DeviceClassList_r.T_sn,
  106. T_remark: DeviceClassList_r.T_remark,
  107. }
  108. c.SetAdjacentDeviceAVGTaskData(T_task_id, device, "", "")
  109. // -----------开始平均复制到结束
  110. continue
  111. } else {
  112. if startTime != list[0].T_time {
  113. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: DeviceClassList_r.T_id + " 找到到自检时间点 " + startTime + " ~ " + list[0].T_time + " 开始自检"})
  114. Task.InsertTaskData(Task_r.T_task_id, Task.TaskData_{
  115. T_sn: list[0].T_sn,
  116. T_id: list[0].T_id,
  117. T_t: list[0].T_t,
  118. T_rh: list[0].T_rh,
  119. T_time: startTime,
  120. })
  121. continue
  122. }
  123. if endTime != list[len(list)-1].T_time {
  124. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: DeviceClassList_r.T_id + " 找到自检时间点 " + list[len(list)-1].T_time + " ~ " + endTime + " 开始自检"})
  125. Task.InsertTaskData(Task_r.T_task_id, Task.TaskData_{
  126. T_sn: list[len(list)-1].T_sn,
  127. T_id: list[len(list)-1].T_id,
  128. T_t: list[len(list)-1].T_t,
  129. T_rh: list[len(list)-1].T_rh,
  130. T_time: endTime,
  131. })
  132. continue
  133. }
  134. }
  135. }
  136. for i := 0; i < len(list)-1; i++ {
  137. current := list[i].T_time
  138. next := list[i+1].T_time
  139. ct, _ := time.Parse("2006-01-02 15:04:05", current)
  140. nt, _ := time.Parse("2006-01-02 15:04:05", next)
  141. interval := nt.Unix() - ct.Unix()
  142. //logs.Debug("时间间隔:", interval, "保存时间:", saveTime)
  143. //fmt.Println("当前:", current, "下一个:", next)
  144. // 缺一个时间点 补漏
  145. if int(interval) == 2*T_saveT {
  146. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: list[i].T_id + " 找到自检时间点 " + current + " ~ " + next + " 开始自检"})
  147. t := ct.Add(time.Second * time.Duration(T_saveT)).Format("2006-01-02 15:04") //时间临时变量
  148. ttt := (list[i].T_t + list[i+1].T_t) / 2
  149. trht := (list[i].T_rh + list[i+1].T_rh) / 2
  150. Task.InsertTaskData(Task_r.T_task_id, Task.TaskData_{
  151. T_sn: list[i].T_sn,
  152. T_id: list[i].T_id,
  153. T_t: ttt,
  154. T_rh: trht,
  155. T_time: t,
  156. })
  157. continue
  158. }
  159. // 缺的数据大于一个时间点,执行平均复制到
  160. if int(interval) > T_saveT {
  161. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: list[i].T_id + " 找到自检时间点 " + current + " ~ " + next + " 开始自检"})
  162. // -----------开始平均复制到
  163. device := Device.DeviceClassList{
  164. T_class: DeviceClassList_r.T_class,
  165. T_id: DeviceClassList_r.T_id,
  166. T_sn: DeviceClassList_r.T_sn,
  167. T_remark: DeviceClassList_r.T_remark,
  168. }
  169. c.SetAdjacentDeviceAVGTaskData(T_task_id, device, "", "")
  170. // -----------开始平均复制到结束
  171. // 平均复制结束,跳出循环
  172. break
  173. }
  174. }
  175. }
  176. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "完成!"})
  177. // Close the connection
  178. c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
  179. }
  180. // 数据持续时间 x 分钟 没有变化
  181. func (c *TaskDataHandleController) SSE_Continuously_unchanged_data() {
  182. T_task_id := c.GetString("T_task_id") // v26nplogbwt1
  183. T_timeout, _ := c.GetInt("T_timeout", 30) // 持续时间
  184. c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream")
  185. c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
  186. c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
  187. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "任务开始......"})
  188. Task_r, err := Task.Read_Task(T_task_id)
  189. if err != nil {
  190. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取任务信息失败!"})
  191. return
  192. }
  193. // 获取 备注 下面关联设备,数量
  194. DeviceClassList_list := Device.Read_DeviceClassList_List_id_By_Terminal(Task_r.T_class, false)
  195. // 选择 数据缺失的终端
  196. var DeleteDeviceClassList []Device.DeviceClassList
  197. for _, DeviceClassList_r := range DeviceClassList_list {
  198. TaskData_list, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, DeviceClassList_r.T_sn, DeviceClassList_r.T_id, "", "", 0, 9999)
  199. if len(TaskData_list) == 0 {
  200. continue
  201. }
  202. maxCount, start, end := Task.FindUnchangedInterval(TaskData_list)
  203. if 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. strings.Contains(DeviceClassList_r.T_remark, "仓库室外测点") {
  209. continue
  210. }
  211. if maxCount > T_timeout {
  212. Task.DeleteTaskDataByTimeRange(T_task_id, DeviceClassList_r.T_sn, DeviceClassList_r.T_id, "", "")
  213. DeleteDeviceClassList = append(DeleteDeviceClassList, DeviceClassList_r)
  214. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "找到" + DeviceClassList_r.T_id + " 探头, " +
  215. "最多连续 " + lib.To_string(maxCount) + " 分钟没有变化," +
  216. "开始时间:" + start + " 结束时间:" + end + "," +
  217. "开始自检"})
  218. }
  219. }
  220. for _, class_ := range DeleteDeviceClassList {
  221. // -----------开始平均复制到
  222. device := Device.DeviceClassList{
  223. T_class: class_.T_class,
  224. T_id: class_.T_id,
  225. T_sn: class_.T_sn,
  226. T_remark: class_.T_remark,
  227. }
  228. c.SetAdjacentDeviceAVGTaskData(T_task_id, device, "", "")
  229. // -----------开始平均复制到结束
  230. }
  231. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "完成!"})
  232. // Close the connection
  233. c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
  234. }
  235. // 区间数据校正 (布点区域数据自检) 均匀性布点,产品存放区域测点 区间数据超标校正 超标数据偏移到区间内
  236. func (c *TaskDataHandleController) SSE_Interval_data_correction() {
  237. T_task_id := c.GetString("T_task_id") // v26nplogbwt1
  238. c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream")
  239. c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
  240. c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
  241. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "任务开始......"})
  242. Task_r, err := Task.Read_Task(T_task_id)
  243. if err != nil {
  244. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取任务信息失败!"})
  245. return
  246. }
  247. 温度控制范围最小值 := float64(lib.To_float32(VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "温度控制范围最小值")))
  248. 温度控制范围最高值 := float64(lib.To_float32(VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "温度控制范围最高值")))
  249. if 温度控制范围最小值 == 0 || 温度控制范围最高值 == 0 {
  250. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温度控制范围 标签值不正确!"})
  251. return
  252. }
  253. // 均匀性布点 产品存放区域测点
  254. 部点终端_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "均匀性布点|产品存放区域测点|作业出入口总测点")
  255. if len(部点终端_list) <= 2 {
  256. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "均匀性布点|产品存放区域测点|作业出入口总测点 太少了,至少两条以上!"})
  257. return
  258. }
  259. 部点终端_sn_list := Device.JoinDeviceClassListSnToString(部点终端_list)
  260. var 开始时间, 结束时间, 趋势时间 string
  261. 开始时间, 结束时间, 趋势时间 = c.GetStartTimeAndEndTime(Task_r, 部点终端_sn_list, 温度控制范围最高值)
  262. if 开始时间 == "" || 结束时间 == "" {
  263. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 开始时间 或 结束时间!"})
  264. return
  265. }
  266. type AVGClassList struct {
  267. T_sn string
  268. T_id string
  269. T_max float64
  270. T_min float64
  271. T_diff float64 // 最大最小值差异
  272. }
  273. fmt.Println("数据准备:", 开始时间, 结束时间, 温度控制范围最小值, 温度控制范围最高值)
  274. // -------------------- 温湿度绑定点vga_H --------------------
  275. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "--- 进行处理 数据!---"})
  276. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: fmt.Sprintf("开始时间:%s 结束时间:%s", 开始时间, 结束时间)})
  277. // 先整体向上偏移
  278. for _, i2 := range 部点终端_list {
  279. T_min := Task.Read_TaskData_min(T_task_id, i2.T_sn, i2.T_id, "", "")
  280. if T_min < RoundToDecimal(温度控制范围最小值+0.1, 1) {
  281. Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, i2.T_sn, i2.T_id, "", "", RoundToDecimal(温度控制范围最小值+0.1-T_min, 1), 0)
  282. }
  283. }
  284. // ----------获取保留数据------------
  285. //var 开空开, 保空开 string
  286. //var 开空开驼峰, 保空开驼峰 Task.CalculateHumps_R
  287. //var valueStrings1, valueStrings2 []string
  288. var BWXValueStrings []string
  289. if Task_r.T_device_type != "X" {
  290. //valueStrings1, valueStrings2, 开空开, 保空开, 开空开驼峰, 保空开驼峰 = c.GetRetainData(Task_r, 部点终端_list, false)
  291. } else {
  292. BWXValueStrings = c.GetBWXRetainData(Task_r, 部点终端_sn_list, 结束时间, 趋势时间)
  293. }
  294. // ----------获取保留数据结束------------
  295. var AVGClassList_r []AVGClassList
  296. for _, i2 := range 部点终端_list {
  297. T_max := Task.Read_TaskData_max(T_task_id, i2.T_sn, i2.T_id, 开始时间, 结束时间)
  298. T_min := Task.Read_TaskData_min(T_task_id, i2.T_sn, i2.T_id, "", "")
  299. 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})
  300. }
  301. for _, AVGClassList_i := range AVGClassList_r {
  302. if AVGClassList_i.T_max < 温度控制范围最高值 && AVGClassList_i.T_min > 温度控制范围最小值 {
  303. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "测点 " + lib.To_string(AVGClassList_i.T_id) +
  304. " 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃ " +
  305. " 最小值:" + lib.To_string(AVGClassList_i.T_min) + "℃ " +
  306. " 符合要求!"})
  307. continue
  308. }
  309. var vgaca float64
  310. if RoundToDecimal(AVGClassList_i.T_max-AVGClassList_i.T_min, 1) > RoundToDecimal(温度控制范围最高值-温度控制范围最小值-0.4, 1) {
  311. // 压缩
  312. diff := RoundToDecimal(AVGClassList_i.T_max-AVGClassList_i.T_min, 1)
  313. // 获取压缩度
  314. compress := RoundToDecimal((温度控制范围最高值-温度控制范围最小值-0.6)/diff, 2)
  315. // 压缩
  316. Task.UpdateTaskDataTemperatureAndHumidityByGeometric(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", compress, 1)
  317. T_max_compress := RoundToDecimal(AVGClassList_i.T_max*compress, 1)
  318. T_min_compress := RoundToDecimal(AVGClassList_i.T_min*compress, 1)
  319. // 判断压缩后是否在 温度控制范围最小值-温度控制范围最高值范围内 不做处理
  320. if T_max_compress <= RoundToDecimal(温度控制范围最高值-0.1, 1) && T_min_compress >= RoundToDecimal(温度控制范围最小值+0.1, 1) {
  321. 参考值 := RoundToDecimal((温度控制范围最高值+温度控制范围最小值)/2, 1)
  322. 中间值 := RoundToDecimal((AVGClassList_i.T_max+AVGClassList_i.T_min)/2, 1)
  323. if 参考值 > 中间值 {
  324. // 向上偏移
  325. vgaca = 参考值 - 中间值
  326. Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", vgaca, 0)
  327. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + lib.To_string(AVGClassList_i.T_id) +
  328. " 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃ " +
  329. " 最小值:" + lib.To_string(AVGClassList_i.T_min) + "℃ " +
  330. " 压缩:" + lib.To_string(compress) +
  331. " 压缩后最大值:" + lib.To_string(T_max_compress) + "℃ " +
  332. " 压缩后最小值:" + lib.To_string(T_min_compress) + "℃ " +
  333. " 向上偏移:" + lib.To_string(vgaca) + "℃ "})
  334. continue
  335. }
  336. if 参考值 < 中间值 {
  337. // 向下偏移
  338. vgaca = 中间值 - 参考值
  339. Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", -vgaca, 0)
  340. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + lib.To_string(AVGClassList_i.T_id) +
  341. " 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃ " +
  342. " 最小值:" + lib.To_string(AVGClassList_i.T_min) + "℃ " +
  343. " 压缩:" + lib.To_string(compress) +
  344. " 压缩后最大值:" + lib.To_string(T_max_compress) + "℃ " +
  345. " 压缩后最小值:" + lib.To_string(T_min_compress) + "℃ " +
  346. " 向下偏移:" + lib.To_string(vgaca) + "℃ "})
  347. continue
  348. }
  349. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + lib.To_string(AVGClassList_i.T_id) +
  350. " 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃ " +
  351. " 最小值:" + lib.To_string(AVGClassList_i.T_min) + "℃ " +
  352. " 压缩:" + lib.To_string(compress) +
  353. " 压缩后最大值:" + lib.To_string(T_max_compress) + "℃ " +
  354. " 压缩后最小值:" + lib.To_string(T_min_compress) + "℃ "})
  355. continue
  356. }
  357. // 压缩后仍高于 温度控制范围最高值,向下偏移
  358. if T_max_compress >= 温度控制范围最高值 {
  359. vgaca = RoundToDecimal((T_max_compress+T_min_compress)/2-(温度控制范围最高值+温度控制范围最小值)/2, 1)
  360. //vgaca = RoundToDecimal(T_max_compress-温度控制范围最高值+0.1, 1)
  361. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + lib.To_string(AVGClassList_i.T_id) +
  362. " 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃ " +
  363. " 最小值:" + lib.To_string(AVGClassList_i.T_min) + "℃ " +
  364. " 压缩:" + lib.To_string(compress) +
  365. " 压缩后最大值:" + lib.To_string(RoundToDecimal(AVGClassList_i.T_max*compress, 1)) + "℃ " +
  366. " 压缩后最小值:" + lib.To_string(RoundToDecimal(AVGClassList_i.T_min*compress, 1)) + "℃ " +
  367. " 数据偏差:" + lib.To_string(vgaca) + "℃ " +
  368. " 向下偏移:" + lib.To_string(vgaca) + "℃ "})
  369. Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", -vgaca, 0)
  370. continue
  371. }
  372. // 压缩后仍低于 温度控制范围最小值,向上偏移
  373. if T_min_compress <= 温度控制范围最小值 {
  374. // 向上偏移
  375. vgaca = RoundToDecimal((温度控制范围最高值+温度控制范围最小值)/2-(T_max_compress+T_min_compress)/2, 1)
  376. //vgaca = RoundToDecimal(温度控制范围最小值-AVGClassList_i.T_min*compress+0.1, 1)
  377. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + lib.To_string(AVGClassList_i.T_id) +
  378. " 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃ " +
  379. " 最小值:" + lib.To_string(AVGClassList_i.T_min) + "℃ " +
  380. " 压缩:" + lib.To_string(compress) +
  381. " 压缩后最大值:" + lib.To_string(RoundToDecimal(AVGClassList_i.T_max*compress, 1)) + "℃ " +
  382. " 压缩后最小值:" + lib.To_string(RoundToDecimal(AVGClassList_i.T_min*compress, 1)) + "℃ " +
  383. " 数据偏差:" + lib.To_string(vgaca) + "℃ " +
  384. " 向上偏移:" + lib.To_string(vgaca) + "℃ "})
  385. Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", vgaca, 0)
  386. }
  387. continue
  388. } else {
  389. // 向下偏移
  390. if AVGClassList_i.T_max >= 温度控制范围最高值 {
  391. vgaca = RoundToDecimal(AVGClassList_i.T_max-温度控制范围最高值+0.2, 1)
  392. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + lib.To_string(AVGClassList_i.T_id) +
  393. " 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃ " +
  394. " 最小值:" + lib.To_string(AVGClassList_i.T_min) + "℃ " +
  395. " 数据偏差:" + lib.To_string(vgaca) + "℃ " +
  396. " 向下偏移:" + lib.To_string(vgaca) + "℃ "})
  397. // 偏移
  398. Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", -vgaca, 0)
  399. continue
  400. }
  401. if AVGClassList_i.T_min <= 温度控制范围最小值 {
  402. vgaca = RoundToDecimal(温度控制范围最小值-AVGClassList_i.T_min+0.2, 1)
  403. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + lib.To_string(AVGClassList_i.T_id) +
  404. " 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃ " +
  405. " 最小值:" + lib.To_string(AVGClassList_i.T_min) + "℃ " +
  406. " 数据偏差: " + lib.To_string(vgaca) + "℃ " +
  407. " 向上偏移:" + lib.To_string(vgaca) + "℃ "})
  408. Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", vgaca, 0)
  409. }
  410. }
  411. }
  412. // ----------恢复保留数据------------
  413. if Task_r.T_device_type != "X" {
  414. //c.SaveRetainData(Task_r, 部点终端_list, valueStrings1, valueStrings2, 开空开, 保空开, 开空开驼峰, 保空开驼峰, 温度控制范围最高值, 60)
  415. } else {
  416. c.SaveBWXRetainData(Task_r, 部点终端_list, BWXValueStrings, 结束时间, 趋势时间, 60)
  417. }
  418. // ----------恢复保留数据结束------------
  419. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "完成!"})
  420. // Close the connection
  421. c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
  422. }
  423. // 绑定点与终端比对 (绑定点数据自检) 终端数据为参照物,绑定点数据在终端偏差±1℃,保温箱为±0.5℃
  424. func (c *TaskDataHandleController) SSE_Comparison_between_binding_points_and_terminals() {
  425. T_task_id := c.GetString("T_task_id") // v26nplogbwt1
  426. T_deviation, _ := c.GetFloat("T_deviation", 1.0) // 误差绑定点数据与终端对比偏差
  427. c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream")
  428. c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
  429. c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
  430. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "任务开始......"})
  431. Task_r, err := Task.Read_Task(T_task_id)
  432. if err != nil {
  433. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取任务信息失败!"})
  434. return
  435. }
  436. // 保温箱偏差为0.5
  437. if Task_r.T_device_type == "X" {
  438. T_deviation = 0.5
  439. }
  440. // -------------------- 获取开始时间--------------------
  441. 温度控制范围最高值 := float64(lib.To_float32(VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "温度控制范围最高值")))
  442. if 温度控制范围最高值 == 0 {
  443. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温度控制范围最高值 标签值不正确!"})
  444. return
  445. }
  446. 温度控制范围最小值 := float64(lib.To_float32(VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "温度控制范围最小值")))
  447. if 温度控制范围最小值 == 0 {
  448. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温度控制范围最小值 标签值不正确!"})
  449. return
  450. }
  451. // 均匀性布点 产品存放区域测点
  452. 部点终端_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "均匀性布点|产品存放区域测点")
  453. if len(部点终端_list) <= 2 {
  454. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "均匀性布点,产品存放区域测点 太少了,至少两条以上!"})
  455. return
  456. }
  457. 部点终端_sn_list := Device.JoinDeviceClassListSnToString(部点终端_list)
  458. var 开始时间, 结束时间, 趋势时间 string
  459. 开始时间, 结束时间, 趋势时间 = c.GetStartTimeAndEndTime(Task_r, 部点终端_sn_list, 温度控制范围最高值)
  460. if 开始时间 == "" || 结束时间 == "" {
  461. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 开始时间 或 结束时间!"})
  462. return
  463. }
  464. // ----------获取保留数据------------
  465. var 开空开, 保空开 string
  466. var 开空开驼峰, 保空开驼峰 Task.CalculateHumps_R
  467. var BWXValueStrings []string
  468. var valueStrings1, valueStrings2 []string
  469. if Task_r.T_device_type != "X" {
  470. valueStrings1, valueStrings2, 开空开, 保空开, 开空开驼峰, 保空开驼峰 = c.GetRetainData(Task_r, 部点终端_list, true)
  471. } else {
  472. BWXValueStrings = c.GetBWXRetainData(Task_r, 部点终端_sn_list, 结束时间, 趋势时间)
  473. }
  474. // ----------获取保留数据结束------------
  475. 监测终端_list := Device.Read_DeviceClassList_List_id_By_Terminal(Task_r.T_class, true)
  476. if len(监测终端_list) < 1 {
  477. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 监测终端!"})
  478. return
  479. }
  480. 温湿度绑定点_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "温湿度绑定点")
  481. if len(温湿度绑定点_list) < 1 {
  482. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 温湿度绑定点!"})
  483. return
  484. }
  485. if len(监测终端_list) != len(温湿度绑定点_list) {
  486. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "监测终端 和 温湿度绑定点 数量不一致!"})
  487. return
  488. }
  489. var 监测终端01, 监测终端02, 温湿度绑定点1, 温湿度绑定点2 Device.DeviceClassList
  490. for _, list := range 监测终端_list {
  491. if strings.Contains(list.T_remark, "监测终端01") {
  492. 监测终端01 = list
  493. }
  494. if strings.Contains(list.T_remark, "监测终端02") {
  495. 监测终端02 = list
  496. }
  497. }
  498. for _, list := range 温湿度绑定点_list {
  499. if strings.Contains(list.T_remark, "温湿度绑定点1") {
  500. 温湿度绑定点1 = list
  501. }
  502. if strings.Contains(list.T_remark, "温湿度绑定点2") {
  503. 温湿度绑定点2 = list
  504. }
  505. }
  506. var 温湿度绑定点vga, 监测终端vga float64
  507. 温湿度绑定点vga = Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点1.T_sn, 温湿度绑定点1.T_id, 开始时间, 结束时间)
  508. if 温湿度绑定点vga == 0 {
  509. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温湿度绑定点1 无数据!请先处理数据!"})
  510. return
  511. }
  512. 监测终端vga = Task.Read_TaskData_AVG(T_task_id, 监测终端01.T_sn, 监测终端01.T_id, 开始时间, 结束时间)
  513. if 监测终端vga == 0 {
  514. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "监测终端01 无数据!请先处理数据!"})
  515. return
  516. }
  517. 温湿度绑定点vga = RoundToDecimal(温湿度绑定点vga, 1)
  518. 监测终端vga = RoundToDecimal(监测终端vga, 1)
  519. if len(监测终端_list) == 1 {
  520. // 只有一个终端,直接偏移到±T_deviation 区间内
  521. if (温湿度绑定点vga > 监测终端vga && 温湿度绑定点vga < 监测终端vga+T_deviation) || (温湿度绑定点vga < 监测终端vga && 温湿度绑定点vga > 监测终端vga-T_deviation) {
  522. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "" +
  523. "温湿度绑定点1平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " +
  524. "监测终端01 平均值" + lib.To_string(监测终端vga) + "℃ " +
  525. "数据偏差: " + lib.To_string(RoundToDecimal(监测终端vga-温湿度绑定点vga, 1)) + "℃ " +
  526. "设置:" + lib.To_string(T_deviation) + "℃" +
  527. "符合要求!"})
  528. }
  529. T_max := Task.Read_TaskData_max(T_task_id, 温湿度绑定点1.T_sn, 温湿度绑定点1.T_id, 开始时间, 结束时间)
  530. T_min := Task.Read_TaskData_min(T_task_id, 温湿度绑定点1.T_sn, 温湿度绑定点1.T_id, 开始时间, 结束时间)
  531. // 平均值向下偏移
  532. if 温湿度绑定点vga > RoundToDecimal(监测终端vga+T_deviation, 1) {
  533. c.SetAverageShiftedDownward(T_task_id, 温湿度绑定点1.T_id, T_deviation, 监测终端vga, 温湿度绑定点vga, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "")
  534. }
  535. // 平均值向上偏移
  536. if 温湿度绑定点vga < RoundToDecimal(监测终端vga-T_deviation, 1) {
  537. c.SetAverageShiftedUpward(T_task_id, 温湿度绑定点1.T_id, T_deviation, 监测终端vga, 温湿度绑定点vga, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "")
  538. }
  539. } else if len(监测终端_list) == 2 {
  540. // 有两个终端,找出目标温湿度绑定点vga, 目标温湿度绑定点2vga最优解后偏移
  541. var 温湿度绑定点2vga, 监测终端2vga float64
  542. 温湿度绑定点2vga = Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点2.T_sn, 温湿度绑定点2.T_id, 开始时间, 结束时间)
  543. if 温湿度绑定点2vga == 0 {
  544. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温湿度绑定点3 无数据!请先处理数据!"})
  545. }
  546. 监测终端2vga = Task.Read_TaskData_AVG(T_task_id, 监测终端02.T_sn, 监测终端02.T_id, 开始时间, 结束时间)
  547. if 监测终端2vga == 0 {
  548. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "监测终端02 无数据!请先处理数据!"})
  549. }
  550. 温湿度绑定点2vga = RoundToDecimal(温湿度绑定点2vga, 1)
  551. 监测终端2vga = RoundToDecimal(监测终端2vga, 1)
  552. if math.Abs(监测终端2vga-监测终端vga) > 3 {
  553. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "监测终端vga|监测终端2vga 绝对值相差超过3度,无法处理!"})
  554. return
  555. }
  556. // 获取监测终端和绑定点的平均值
  557. 目标温湿度绑定点vga, 目标温湿度绑定点2vga, isExist := findBindingPointsOptimalAdjustment(监测终端vga, 监测终端2vga, 温湿度绑定点vga, 温湿度绑定点2vga, T_deviation)
  558. 目标温湿度绑定点vga = RoundToDecimal(目标温湿度绑定点vga, 1)
  559. 目标温湿度绑定点2vga = RoundToDecimal(目标温湿度绑定点2vga, 1)
  560. if !isExist {
  561. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "监测终端01 平均值" + lib.To_string(监测终端vga) + "℃ " +
  562. "监测终端02 平均值" + lib.To_string(监测终端2vga) + "℃ " +
  563. "未找到 最优 温湿度绑定点1、温湿度绑定点2 调整值!"})
  564. return
  565. }
  566. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "监测终端01 平均值" + lib.To_string(监测终端vga) + "℃ " +
  567. "监测终端02 平均值" + lib.To_string(监测终端2vga) + "℃ " +
  568. "温湿度绑定点1 原始平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " +
  569. "温湿度绑定点2 原始平均值:" + lib.To_string(温湿度绑定点2vga) + "℃ " +
  570. "温湿度绑定点1 最优平均值:" + lib.To_string(目标温湿度绑定点vga) + "℃ " +
  571. "温湿度绑定点2 最优平均值:" + lib.To_string(目标温湿度绑定点2vga) + "℃ " +
  572. "设置:" + lib.To_string(T_deviation) + "℃"})
  573. if 目标温湿度绑定点vga != 温湿度绑定点vga {
  574. T_max := Task.Read_TaskData_max(T_task_id, 温湿度绑定点1.T_sn, 温湿度绑定点1.T_id, 开始时间, 结束时间)
  575. T_min := Task.Read_TaskData_min(T_task_id, 温湿度绑定点1.T_sn, 温湿度绑定点1.T_id, 开始时间, 结束时间)
  576. // 平均值向下偏移
  577. if 温湿度绑定点vga > RoundToDecimal(目标温湿度绑定点vga, 1) {
  578. c.SetAverageShiftedDownward(T_task_id, 温湿度绑定点1.T_id, 0, 目标温湿度绑定点vga, 温湿度绑定点vga, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "")
  579. }
  580. // 平均值向上偏移
  581. if 温湿度绑定点vga < RoundToDecimal(目标温湿度绑定点vga, 1) {
  582. c.SetAverageShiftedUpward(T_task_id, 温湿度绑定点1.T_id, 0, 目标温湿度绑定点vga, 温湿度绑定点vga, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "")
  583. }
  584. }
  585. if 目标温湿度绑定点2vga != 温湿度绑定点2vga {
  586. T_max := Task.Read_TaskData_max(T_task_id, 温湿度绑定点2.T_sn, 温湿度绑定点2.T_id, 开始时间, 结束时间)
  587. T_min := Task.Read_TaskData_min(T_task_id, 温湿度绑定点2.T_sn, 温湿度绑定点2.T_id, 开始时间, 结束时间)
  588. // 平均值向下偏移
  589. if 温湿度绑定点2vga > RoundToDecimal(目标温湿度绑定点2vga, 1) {
  590. c.SetAverageShiftedDownward(T_task_id, 温湿度绑定点2.T_id, 0, 目标温湿度绑定点2vga, 温湿度绑定点2vga, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "")
  591. }
  592. // 平均值向上偏移
  593. if 温湿度绑定点2vga < RoundToDecimal(目标温湿度绑定点2vga, 1) {
  594. c.SetAverageShiftedUpward(T_task_id, 温湿度绑定点2.T_id, 0, 目标温湿度绑定点2vga, 温湿度绑定点2vga, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "")
  595. }
  596. }
  597. }
  598. // ----------恢复保留数据------------
  599. if Task_r.T_device_type != "X" {
  600. c.SaveRetainData(Task_r, 部点终端_list, valueStrings1, valueStrings2, 开空开, 保空开, 开空开驼峰, 保空开驼峰, 温度控制范围最高值, 60)
  601. } else {
  602. c.SaveBWXRetainData(Task_r, 部点终端_list, BWXValueStrings, 结束时间, 趋势时间, 60)
  603. }
  604. // ----------恢复保留数据结束------------
  605. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "完成!"})
  606. // Close the connection
  607. c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
  608. }
  609. /*
  610. 绑定点与冷热点比对 (冷热点数据自检)绑定点数据为参照物,绑定点数据在终端偏差±1℃,保温箱为±0.5℃
  611. 固定偏移一固定值,降到超限的平均复制,仍然超限再压缩
  612. */
  613. func (c *TaskDataHandleController) SSE_Compare_binding_points_with_cold_and_hot_spots() {
  614. T_task_id := c.GetString("T_task_id") // v26nplogbwt1
  615. T_deviation, _ := c.GetFloat("T_deviation", 1.0) // 偏差时间
  616. c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream")
  617. c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
  618. c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
  619. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "任务开始......"})
  620. Task_r, err := Task.Read_Task(T_task_id)
  621. if err != nil {
  622. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取任务信息失败!"})
  623. return
  624. }
  625. // 保温箱偏差为0.5
  626. if Task_r.T_device_type == "X" {
  627. T_deviation = 0.5
  628. }
  629. 温度控制范围最高值 := float64(lib.To_float32(VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "温度控制范围最高值")))
  630. if 温度控制范围最高值 == 0 {
  631. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温度控制范围最高值 标签值不正确!"})
  632. return
  633. }
  634. 温度控制范围最小值 := float64(lib.To_float32(VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "温度控制范围最小值")))
  635. if 温度控制范围最小值 == 0 {
  636. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温度控制范围最小值 标签值不正确!"})
  637. return
  638. }
  639. // ------- 温湿度绑定点
  640. 温湿度绑定点1_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "温湿度绑定点1")
  641. if len(温湿度绑定点1_list) != 1 {
  642. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温湿度绑定点1 中找到 " + lib.To_string(len(温湿度绑定点1_list)) + "条,布点终端异常!"})
  643. return
  644. }
  645. 温湿度绑定点2_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "温湿度绑定点2")
  646. if len(温湿度绑定点2_list) != 1 {
  647. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "温湿度绑定点2 没找到,将 温湿度绑定点1 设置低点"})
  648. 温湿度绑定点2_list = 温湿度绑定点1_list
  649. }
  650. // 均匀性布点 产品存放区域测点
  651. 部点终端_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "均匀性布点|产品存放区域测点")
  652. if len(部点终端_list) == 0 {
  653. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "没有找到 均匀性布点,产品存放区域测点,作业出入口总测点 测点数据!"})
  654. return
  655. }
  656. 部点终端_sn_list := Device.JoinDeviceClassListSnToString(部点终端_list)
  657. var 开始时间, 结束时间, 趋势时间 string
  658. 开始时间, 结束时间, 趋势时间 = c.GetStartTimeAndEndTime(Task_r, 部点终端_sn_list, 温度控制范围最高值)
  659. if 开始时间 == "" || 结束时间 == "" {
  660. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 开始时间 或 结束时间!"})
  661. return
  662. }
  663. // ----------获取保留数据------------
  664. var 开空开, 保空开 string
  665. var 开空开驼峰, 保空开驼峰 Task.CalculateHumps_R
  666. var BWXValueStrings []string
  667. var valueStrings1, valueStrings2 []string
  668. if Task_r.T_device_type != "X" {
  669. valueStrings1, valueStrings2, 开空开, 保空开, 开空开驼峰, 保空开驼峰 = c.GetRetainData(Task_r, 部点终端_list, true)
  670. } else {
  671. BWXValueStrings = c.GetBWXRetainData(Task_r, 部点终端_sn_list, 结束时间, 趋势时间)
  672. }
  673. // ----------获取保留数据结束------------
  674. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "--- 开始时间--- " + 开始时间})
  675. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "--- 结束时间--- " + 结束时间})
  676. type AVGClassList struct {
  677. T_id string
  678. T_vga float64
  679. T_max float64
  680. T_min float64
  681. }
  682. 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), 开始时间, 结束时间)
  683. if len(TaskData_Total_GroupBySnId) == 0 {
  684. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温湿度绑定点 无数据"})
  685. return
  686. }
  687. for _, v := range TaskData_Total_GroupBySnId {
  688. if v.Total == 0 {
  689. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温湿度绑定点[" + v.T_id + "] 无数据"})
  690. return
  691. }
  692. }
  693. 温湿度绑定点1vga := Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点1_list[0].T_sn, 温湿度绑定点1_list[0].T_id, 开始时间, 结束时间)
  694. 温湿度绑定点2vga := Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点2_list[0].T_sn, 温湿度绑定点2_list[0].T_id, 开始时间, 结束时间)
  695. if 温湿度绑定点1vga == 温湿度绑定点2vga {
  696. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "温湿度绑定点1 与 温湿度绑定点2 平均值相等,将 进行上下偏移处理!"})
  697. 温湿度绑定点1vga += T_deviation / 2
  698. 温湿度绑定点2vga -= T_deviation / 2
  699. T_deviation /= 2
  700. }
  701. var 温湿度绑定点vga_H, 温湿度绑定点vga_L AVGClassList
  702. if 温湿度绑定点1vga > 温湿度绑定点2vga {
  703. 温湿度绑定点vga_H.T_id = 温湿度绑定点1_list[0].T_id
  704. 温湿度绑定点vga_H.T_vga = RoundToDecimal(温湿度绑定点1vga, 1)
  705. 温湿度绑定点vga_L.T_id = 温湿度绑定点2_list[0].T_id
  706. 温湿度绑定点vga_L.T_vga = RoundToDecimal(温湿度绑定点2vga, 1)
  707. } else {
  708. 温湿度绑定点vga_L.T_id = 温湿度绑定点1_list[0].T_id
  709. 温湿度绑定点vga_L.T_vga = RoundToDecimal(温湿度绑定点1vga, 1)
  710. 温湿度绑定点vga_H.T_id = 温湿度绑定点2_list[0].T_id
  711. 温湿度绑定点vga_H.T_vga = RoundToDecimal(温湿度绑定点2vga, 1)
  712. }
  713. fmt.Println("温湿度绑定点:", 温湿度绑定点vga_H, 温湿度绑定点vga_L)
  714. var Average_H_List []Task.TaskData_Average // 热点
  715. var Average_L_List []Task.TaskData_Average // 冷点
  716. snList := Device.JoinDeviceClassListSnToString(部点终端_list)
  717. TaskData_Average_GroupBySnId := Task.Read_TaskData_Average_GroupBySnId(Task_r.T_task_id, snList, 开始时间, 结束时间)
  718. if len(TaskData_Average_GroupBySnId) < 2 {
  719. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "未找到 均匀性布点,产品存放区域测点 数据冷热点,平均值数据少于2条!"})
  720. return
  721. }
  722. for _, average := range TaskData_Average_GroupBySnId {
  723. if RoundToDecimal(average.Average, 1) > RoundToDecimal(温湿度绑定点vga_H.T_vga+T_deviation, 1) {
  724. average.Average = RoundToDecimal(average.Average, 1)
  725. Average_H_List = append(Average_H_List, average)
  726. }
  727. if RoundToDecimal(average.Average, 1) < RoundToDecimal(温湿度绑定点vga_L.T_vga-T_deviation, 1) {
  728. average.Average = RoundToDecimal(average.Average, 1)
  729. Average_L_List = append(Average_L_List, average)
  730. }
  731. }
  732. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "------ 进行 高点处理 ------"})
  733. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "------ 高点平均值 " + lib.To_string(温湿度绑定点vga_H.T_vga) + "------"})
  734. if len(Average_H_List) == 0 {
  735. Average_H := TaskData_Average_GroupBySnId[0]
  736. // 高点不在冷热点范围
  737. if RoundToDecimal(Average_H.Average, 1) < RoundToDecimal(温湿度绑定点vga_H.T_vga-T_deviation, 1) &&
  738. RoundToDecimal(Average_H.Average, 1) > RoundToDecimal(温湿度绑定点vga_L.T_vga+T_deviation, 1) {
  739. // 热点向上偏移到高点-T_deviation
  740. T_max := Task.Read_TaskData_max(T_task_id, Average_H.T_sn, Average_H.T_id, 开始时间, 结束时间)
  741. T_min := Task.Read_TaskData_min(T_task_id, Average_H.T_sn, Average_H.T_id, 开始时间, 结束时间)
  742. c.SetAverageShiftedUpward(T_task_id, Average_H.T_id, T_deviation, 温湿度绑定点vga_H.T_vga, Average_H.Average, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "")
  743. }
  744. } else {
  745. for _, Average_H := range Average_H_List {
  746. // 热点向下偏移到高点范围
  747. T_max := Task.Read_TaskData_max(T_task_id, Average_H.T_sn, Average_H.T_id, 开始时间, 结束时间)
  748. T_min := Task.Read_TaskData_min(T_task_id, Average_H.T_sn, Average_H.T_id, 开始时间, 结束时间)
  749. c.SetAverageShiftedDownward(T_task_id, Average_H.T_id, T_deviation, 温湿度绑定点vga_H.T_vga, Average_H.Average, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "")
  750. }
  751. }
  752. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "------ 进行 低点处理 ------"})
  753. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "------ 低点平均值 " + lib.To_string(温湿度绑定点vga_L.T_vga) + "------"})
  754. if len(Average_L_List) == 0 {
  755. Average_L := TaskData_Average_GroupBySnId[0]
  756. // 冷点不在冷热点范围
  757. if RoundToDecimal(Average_L.Average, 1) < RoundToDecimal(温湿度绑定点vga_L.T_vga+T_deviation, 1) &&
  758. RoundToDecimal(Average_L.Average, 1) < RoundToDecimal(温湿度绑定点vga_L.T_vga-T_deviation, 1) {
  759. // 热点向下偏移到高点范围
  760. T_max := Task.Read_TaskData_max(T_task_id, Average_L.T_sn, Average_L.T_id, 开始时间, 结束时间)
  761. T_min := Task.Read_TaskData_min(T_task_id, Average_L.T_sn, Average_L.T_id, 开始时间, 结束时间)
  762. c.SetAverageShiftedDownward(T_task_id, Average_L.T_id, T_deviation, 温湿度绑定点vga_H.T_vga, Average_L.Average, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "")
  763. }
  764. } else {
  765. for _, Average_L := range Average_L_List {
  766. // 热点向下偏移到高点范围
  767. T_max := Task.Read_TaskData_max(T_task_id, Average_L.T_sn, Average_L.T_id, 开始时间, 结束时间)
  768. T_min := Task.Read_TaskData_min(T_task_id, Average_L.T_sn, Average_L.T_id, 开始时间, 结束时间)
  769. c.SetAverageShiftedUpward(T_task_id, Average_L.T_id, T_deviation, 温湿度绑定点vga_L.T_vga, Average_L.Average, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "")
  770. }
  771. }
  772. // ----------恢复保留数据------------
  773. if Task_r.T_device_type != "X" {
  774. c.SaveRetainData(Task_r, 部点终端_list, valueStrings1, valueStrings2, 开空开, 保空开, 开空开驼峰, 保空开驼峰, 温度控制范围最高值, 60)
  775. } else {
  776. c.SaveBWXRetainData(Task_r, 部点终端_list, BWXValueStrings, 结束时间, 趋势时间, 60)
  777. }
  778. // ----------恢复保留数据结束------------
  779. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "完成!"})
  780. // Close the connection
  781. c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
  782. }
  783. // 获取相邻2个终端值平均复制到
  784. func (c *TaskDataHandleController) SetAdjacentDeviceAVGTaskData(T_task_id string, device Device.DeviceClassList, StartTime, EndTime string) {
  785. DeviceClassListT_remark_r := Device.Read_DeviceClassList_List_id_T_remark(device.T_class, device.T_remark)
  786. // 分组统计每个sn的数据数量
  787. snList := Device.JoinDeviceClassListSnToString(DeviceClassListT_remark_r)
  788. TaskData_Total_GroupBySnId := Task.Read_TaskData_Total_GroupBySnId(T_task_id, snList, StartTime, EndTime)
  789. if len(TaskData_Total_GroupBySnId) < 2 {
  790. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "[" + device.T_remark + "]中没有找到 至少2条 可用数据"})
  791. return
  792. }
  793. // 获取 备注 下面关联设备,数量
  794. DeviceClassListT_remark_r_list_MAX := TaskData_Total_GroupBySnId[0].Total
  795. TaskData_Total_GroupBySnId_Map := make(map[string]int64)
  796. for _, v := range TaskData_Total_GroupBySnId {
  797. TaskData_Total_GroupBySnId_Map[v.T_sn] = v.Total
  798. }
  799. var completeDataDeviceClassList []Device.DeviceClassList
  800. for _, v := range DeviceClassListT_remark_r {
  801. if TaskData_Total_GroupBySnId_Map[v.T_sn] == DeviceClassListT_remark_r_list_MAX || v.T_sn == device.T_sn {
  802. completeDataDeviceClassList = append(completeDataDeviceClassList, v)
  803. }
  804. }
  805. if len(completeDataDeviceClassList) < 3 {
  806. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "[" + device.T_remark + "]中没有找到 至少2条 完整可用数据"})
  807. return
  808. }
  809. twoDevice := getBeforeAndAfter(device.T_id, completeDataDeviceClassList)
  810. sn1, id_str1 := twoDevice[0].T_sn, twoDevice[0].T_id
  811. sn2, id_str2 := twoDevice[1].T_sn, twoDevice[1].T_id
  812. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: device.T_sn + "," + device.T_id + "开始平均复制到" +
  813. fmt.Sprintf("%s,%s|%s,%s", sn1, id_str1, sn2, id_str2)})
  814. List1, _ := Task.Read_TaskData_ById_List_AES(T_task_id, sn1, id_str1, StartTime, EndTime, 0, 9999)
  815. List2, _ := Task.Read_TaskData_ById_List_AES(T_task_id, sn2, id_str2, StartTime, EndTime, 0, 9999)
  816. num := len(List1)
  817. if len(List2) < len(List1) {
  818. num = len(List2)
  819. }
  820. if num == 0 {
  821. return
  822. }
  823. T_saveT := 60
  824. //var list []Task.TaskData_
  825. ct, _ := lib.TimeStrToTime(List1[0].T_time)
  826. var valueStrings []string
  827. for i := 0; i < num; i++ {
  828. if List1[i].T_time != List2[i].T_time {
  829. 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)})
  830. return
  831. }
  832. T_t := (List1[i].T_t + List2[i].T_t) / 2
  833. T_rh := (List1[i].T_rh + List2[i].T_rh) / 2
  834. 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")))
  835. ct = ct.Add(time.Second * time.Duration(T_saveT))
  836. }
  837. Task.DeleteTaskDataByTimeRange(T_task_id, device.T_sn, device.T_id, StartTime, EndTime)
  838. err := Task.Batch_Adds_TaskData(T_task_id, valueStrings)
  839. if err == nil {
  840. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: fmt.Sprintf("%d/%d", len(valueStrings), len(valueStrings))})
  841. }
  842. }
  843. func getBeforeAndAfter(T_id string, data []Device.DeviceClassList) []Device.DeviceClassList {
  844. var result []Device.DeviceClassList
  845. var index int
  846. for i, d := range data {
  847. if d.T_id == T_id {
  848. index = i
  849. break
  850. }
  851. }
  852. if index == 0 {
  853. result = append(result, data[len(data)-1], data[1])
  854. } else if index == len(data)-1 {
  855. result = append(result, data[len(data)-2], data[0])
  856. } else {
  857. result = append(result, data[index-1], data[index+1])
  858. }
  859. return result
  860. }
  861. func RoundToDecimal(num float64, decimal int) float64 {
  862. shift := math.Pow(10, float64(decimal))
  863. return math.Round(num*shift) / shift
  864. }
  865. /*
  866. 数据自检名称:平均值数据自检
  867. 测点:柜内所有测点|箱内所有测点|均匀性布点和产品存放区域测点、温湿度绑定点01、温湿度绑定点02
  868. 时间:采用“绑定点数据自检”的时间
  869. 策略:先执行完成“绑定点数据自检”后,温湿度绑定点01和温湿度绑定点02的数据就作为基准数据不变,温湿度绑定点01平均值与柜内所有测点平均值之间的差异在±0.5℃范围以内,温湿度绑定点02平均值与柜内所有测点平均值之间的差异在±0.5℃范围以内,若柜内所有测点的平均值较大或较小,则对柜内所有测点中平均值较大或较小的测点曲线进行偏移调整,使柜内所有测点的平均值靠近温湿度绑定点的平均值,从而达到绑定点与柜内所有测点的平均值差异在±0.5℃。以上“柜内所有测点”要分别换成“箱内所有测点”、“均匀性布点和产品存放区域测点”;“平均值数据自检”和“冷热点数据自检”可以同时勾选(冷库和冷车会用到)进行自检也可以单独执行(冷柜和保温箱只执行“平均值数据自检”)
  870. */
  871. func (c *TaskDataHandleController) SSE_Compare_binding_points_with_Average() {
  872. T_task_id := c.GetString("T_task_id") // v26nplogbwt1
  873. T_deviation := 0.5 // 偏差时间
  874. c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream")
  875. c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
  876. c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
  877. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "任务开始......"})
  878. Task_r, err := Task.Read_Task(T_task_id)
  879. if err != nil {
  880. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取任务信息失败!"})
  881. return
  882. }
  883. // 保温箱偏差为0.5
  884. if Task_r.T_device_type == "X" {
  885. T_deviation = 0.5
  886. }
  887. 温度控制范围最高值 := float64(lib.To_float32(VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "温度控制范围最高值")))
  888. if 温度控制范围最高值 == 0 {
  889. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温度控制范围最高值 标签值不正确!"})
  890. return
  891. }
  892. 温度控制范围最小值 := float64(lib.To_float32(VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "温度控制范围最小值")))
  893. if 温度控制范围最小值 == 0 {
  894. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温度控制范围最小值 标签值不正确!"})
  895. return
  896. }
  897. // 均匀性布点 产品存放区域测点
  898. 部点终端_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "均匀性布点|柜内所有测点|箱内所有测点|产品存放区域测点")
  899. 部点终端_sn_list := Device.JoinDeviceClassListSnToString(部点终端_list)
  900. var 开始时间, 结束时间, 趋势时间 string
  901. 开始时间, 结束时间, 趋势时间 = c.GetStartTimeAndEndTime(Task_r, 部点终端_sn_list, 温度控制范围最高值)
  902. if 开始时间 == "" || 结束时间 == "" {
  903. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 开始时间 或 结束时间!"})
  904. return
  905. }
  906. // ----------获取保留数据------------
  907. var 开空开, 保空开 string
  908. var 开空开驼峰, 保空开驼峰 Task.CalculateHumps_R
  909. var BWXValueStrings []string
  910. var valueStrings1, valueStrings2 []string
  911. if Task_r.T_device_type != "X" {
  912. valueStrings1, valueStrings2, 开空开, 保空开, 开空开驼峰, 保空开驼峰 = c.GetRetainData(Task_r, 部点终端_list, true)
  913. } else {
  914. BWXValueStrings = c.GetBWXRetainData(Task_r, 部点终端_sn_list, 结束时间, 趋势时间)
  915. }
  916. // ----------获取保留数据结束------------
  917. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "--- 开始时间--- " + 开始时间})
  918. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "--- 结束时间--- " + 结束时间})
  919. if len(部点终端_list) == 0 {
  920. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "没有找到 柜内所有测点|箱内所有测点|均匀性布点|产品存放区域测点 测点数据!"})
  921. return
  922. }
  923. snList := Device.JoinDeviceClassListSnToString(部点终端_list)
  924. originalAvg := Task.Read_TaskData_Average(Task_r.T_task_id, snList, 开始时间, 结束时间)
  925. originalAvg = RoundToDecimal(originalAvg, 1)
  926. 温湿度绑定点_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "温湿度绑定点")
  927. if len(温湿度绑定点_list) < 1 {
  928. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 温湿度绑定点!"})
  929. return
  930. }
  931. var 温湿度绑定点1, 温湿度绑定点2 Device.DeviceClassList
  932. for _, list := range 温湿度绑定点_list {
  933. if strings.Contains(list.T_remark, "温湿度绑定点1") {
  934. 温湿度绑定点1 = list
  935. }
  936. if strings.Contains(list.T_remark, "温湿度绑定点2") {
  937. 温湿度绑定点2 = list
  938. }
  939. }
  940. 温湿度绑定点vga := Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点1.T_sn, 温湿度绑定点1.T_id, 开始时间, 结束时间)
  941. 温湿度绑定点vga = RoundToDecimal(温湿度绑定点vga, 1)
  942. if 温湿度绑定点vga == 0 {
  943. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温湿度绑定点1 无数据!请先处理数据!"})
  944. return
  945. }
  946. if len(温湿度绑定点_list) == 1 {
  947. 温湿度绑定点vga = RoundToDecimal(温湿度绑定点vga, 1)
  948. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "------ 进行 柜内所有测点|箱内所有测点|均匀性布点|产品存放区域测点 平均值处理 ------"})
  949. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "" +
  950. "温湿度绑定点1 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " +
  951. "测点 平均值" + lib.To_string(originalAvg) + "℃ " +
  952. "数据偏差: " + lib.To_string(RoundToDecimal(math.Abs(originalAvg-温湿度绑定点vga), 1)) + "℃ " +
  953. "设置:" + lib.To_string(T_deviation) + "℃"})
  954. if (originalAvg >= 温湿度绑定点vga && originalAvg <= 温湿度绑定点vga+T_deviation) || (originalAvg <= 温湿度绑定点vga && originalAvg >= 温湿度绑定点vga-T_deviation) {
  955. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "" +
  956. "温湿度绑定点1 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " +
  957. "测点 平均值" + lib.To_string(originalAvg) + "℃ " +
  958. "数据偏差: " + lib.To_string(RoundToDecimal(math.Abs(originalAvg-温湿度绑定点vga), 1)) + "℃ " +
  959. "设置:" + lib.To_string(T_deviation) + "℃" +
  960. "符合要求!"})
  961. } else {
  962. // 平均值最低点向上偏移
  963. if originalAvg < 温湿度绑定点vga-T_deviation {
  964. k := 0
  965. for originalAvg < 温湿度绑定点vga-T_deviation {
  966. if k == len(部点终端_sn_list) {
  967. // 调整所有平均值都不符合要求,直接停止
  968. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "调整所有测点平均值后均不符合要求!"})
  969. break
  970. }
  971. TaskData_Average_GroupBySnId := Task.Read_TaskData_Average_GroupBySnId(Task_r.T_task_id, snList, 开始时间, 结束时间)
  972. if len(TaskData_Average_GroupBySnId) == 0 {
  973. break
  974. }
  975. Average_L := TaskData_Average_GroupBySnId[len(TaskData_Average_GroupBySnId)-1]
  976. T_max := Task.Read_TaskData_max(T_task_id, Average_L.T_sn, Average_L.T_id, 开始时间, 结束时间)
  977. T_min := Task.Read_TaskData_min(T_task_id, Average_L.T_sn, Average_L.T_id, 开始时间, 结束时间)
  978. c.SetAverageShiftedUpward(T_task_id, Average_L.T_id, T_deviation, RoundToDecimal(温湿度绑定点vga-T_deviation, 1), RoundToDecimal(Average_L.Average, 1), T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "")
  979. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "" +
  980. "温湿度绑定点1 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " +
  981. "测点 平均值" + lib.To_string(originalAvg) + "℃ " +
  982. "数据偏差: " + lib.To_string(RoundToDecimal(温湿度绑定点vga-T_deviation-originalAvg, 1)) + "℃ " +
  983. "设置:" + lib.To_string(T_deviation) + "℃" +
  984. "平均值向上偏移0.1℃"})
  985. originalAvg = Task.Read_TaskData_Average(Task_r.T_task_id, snList, 开始时间, 结束时间)
  986. originalAvg = RoundToDecimal(originalAvg, 1)
  987. k++
  988. }
  989. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "" +
  990. "温湿度绑定点1 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " +
  991. "测点 平均值" + lib.To_string(originalAvg) + "℃ " +
  992. "数据偏差: " + lib.To_string(RoundToDecimal(温湿度绑定点vga-T_deviation-originalAvg, 1)) + "℃ " +
  993. "设置:" + lib.To_string(T_deviation) + "℃" +
  994. "符合要求!"})
  995. }
  996. // 向下偏移
  997. if originalAvg > 温湿度绑定点vga+T_deviation {
  998. l := 0
  999. for originalAvg > 温湿度绑定点vga+T_deviation {
  1000. if l == len(部点终端_sn_list) {
  1001. // 调整所有平均值都不符合要求,直接停止
  1002. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "调整所有测点平均值后均不符合要求!"})
  1003. break
  1004. }
  1005. // 热点向下偏移到高点范围
  1006. TaskData_Average_GroupBySnId := Task.Read_TaskData_Average_GroupBySnId(Task_r.T_task_id, snList, 开始时间, 结束时间)
  1007. if len(TaskData_Average_GroupBySnId) == 0 {
  1008. break
  1009. }
  1010. Average_H := TaskData_Average_GroupBySnId[0]
  1011. T_max := Task.Read_TaskData_max(T_task_id, Average_H.T_sn, Average_H.T_id, 开始时间, 结束时间)
  1012. T_min := Task.Read_TaskData_min(T_task_id, Average_H.T_sn, Average_H.T_id, 开始时间, 结束时间)
  1013. c.SetAverageShiftedDownward(T_task_id, Average_H.T_id, T_deviation, RoundToDecimal(温湿度绑定点vga+T_deviation, 1), Average_H.Average, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "")
  1014. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "" +
  1015. "温湿度绑定点1 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " +
  1016. "测点 平均值" + lib.To_string(originalAvg) + "℃ " +
  1017. "数据偏差: " + lib.To_string(RoundToDecimal(originalAvg-(温湿度绑定点vga+T_deviation), 1)) + "℃ " +
  1018. "设置:" + lib.To_string(T_deviation) + "℃"})
  1019. originalAvg = Task.Read_TaskData_Average(Task_r.T_task_id, snList, 开始时间, 结束时间)
  1020. originalAvg = RoundToDecimal(originalAvg, 1)
  1021. l++
  1022. }
  1023. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "" +
  1024. "温湿度绑定点1 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " +
  1025. "测点 平均值" + lib.To_string(originalAvg) + "℃ " +
  1026. "数据偏差: " + lib.To_string(RoundToDecimal(originalAvg-(温湿度绑定点vga+T_deviation), 1)) + "℃ " +
  1027. "设置:" + lib.To_string(T_deviation) + "℃" +
  1028. "符合要求!"})
  1029. }
  1030. }
  1031. } else if len(温湿度绑定点_list) == 2 {
  1032. 温湿度绑定点2vga := Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点2.T_sn, 温湿度绑定点2.T_id, 开始时间, 结束时间)
  1033. 温湿度绑定点2vga = RoundToDecimal(温湿度绑定点2vga, 1)
  1034. if 温湿度绑定点2vga == 0 {
  1035. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温湿度绑定点2 无数据!请先处理数据!"})
  1036. return
  1037. }
  1038. // 获取最优平均值
  1039. 目标originalAvg := findAverageOptimalAdjustment(温湿度绑定点vga, 温湿度绑定点2vga, originalAvg)
  1040. 目标originalAvg = RoundToDecimal(目标originalAvg, 1)
  1041. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "" +
  1042. " 温湿度绑定点1 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " +
  1043. " 温湿度绑定点2 平均值:" + lib.To_string(温湿度绑定点2vga) + "℃ " +
  1044. " 测点 平均值" + lib.To_string(originalAvg) + "℃ " +
  1045. " 最优 平均值" + lib.To_string(目标originalAvg) + "℃ " +
  1046. " 数据偏差: " + lib.To_string(RoundToDecimal(RoundToDecimal(originalAvg-目标originalAvg, 1), 1)) + "℃ " +
  1047. " 设置:" + lib.To_string(T_deviation) + "℃"})
  1048. if 目标originalAvg != originalAvg {
  1049. // 平均值最低点向上偏移
  1050. if originalAvg < 目标originalAvg {
  1051. j := 0
  1052. for originalAvg < 目标originalAvg {
  1053. if j == len(部点终端_sn_list) {
  1054. // 调整所有平均值都不符合要求,直接停止
  1055. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "调整所有测点平均值后均不符合要求!"})
  1056. break
  1057. }
  1058. TaskData_Average_GroupBySnId := Task.Read_TaskData_Average_GroupBySnId(Task_r.T_task_id, snList, 开始时间, 结束时间)
  1059. if len(TaskData_Average_GroupBySnId) == 0 {
  1060. break
  1061. }
  1062. Average_L := TaskData_Average_GroupBySnId[len(TaskData_Average_GroupBySnId)-1]
  1063. T_max := Task.Read_TaskData_max(T_task_id, Average_L.T_sn, Average_L.T_id, 开始时间, 结束时间)
  1064. T_min := Task.Read_TaskData_min(T_task_id, Average_L.T_sn, Average_L.T_id, 开始时间, 结束时间)
  1065. c.SetAverageShiftedUpward(T_task_id, Average_L.T_id, T_deviation, 目标originalAvg, RoundToDecimal(Average_L.Average, 1), T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "")
  1066. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "" +
  1067. " 温湿度绑定点1 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " +
  1068. " 温湿度绑定点2 平均值:" + lib.To_string(温湿度绑定点2vga) + "℃ " +
  1069. " 测点 平均值" + lib.To_string(originalAvg) + "℃ " +
  1070. " 测点 最优平均值" + lib.To_string(目标originalAvg) + "℃ " +
  1071. " 数据偏差: " + lib.To_string(math.Abs(originalAvg-目标originalAvg)) + "℃ " +
  1072. " 设置:" + lib.To_string(T_deviation) + "℃" +
  1073. " 冷点:" + Average_L.T_id})
  1074. originalAvg = Task.Read_TaskData_Average(Task_r.T_task_id, snList, 开始时间, 结束时间)
  1075. originalAvg = RoundToDecimal(originalAvg, 1)
  1076. j++
  1077. }
  1078. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "" +
  1079. " 温湿度绑定点1 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " +
  1080. " 温湿度绑定点2 平均值:" + lib.To_string(温湿度绑定点2vga) + "℃ " +
  1081. " 测点 平均值" + lib.To_string(originalAvg) + "℃ " +
  1082. " 测点 最优平均值" + lib.To_string(目标originalAvg) + "℃ " +
  1083. " 数据偏差: " + lib.To_string(RoundToDecimal(math.Abs(originalAvg-温湿度绑定点vga), 1)) + "℃ " +
  1084. " 设置:" + lib.To_string(T_deviation) + "℃" +
  1085. " 符合要求!"})
  1086. }
  1087. // 向下偏移
  1088. if originalAvg > 目标originalAvg {
  1089. i := 0
  1090. for originalAvg > 目标originalAvg {
  1091. if i == len(部点终端_sn_list) {
  1092. // 调整所有平均值都不符合要求,直接停止
  1093. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "调整所有测点平均值后均不符合要求!"})
  1094. break
  1095. }
  1096. // 热点向下偏移到高点范围
  1097. TaskData_Average_GroupBySnId := Task.Read_TaskData_Average_GroupBySnId(Task_r.T_task_id, snList, 开始时间, 结束时间)
  1098. if len(TaskData_Average_GroupBySnId) == 0 {
  1099. break
  1100. }
  1101. Average_H := TaskData_Average_GroupBySnId[0]
  1102. T_max := Task.Read_TaskData_max(T_task_id, Average_H.T_sn, Average_H.T_id, 开始时间, 结束时间)
  1103. T_min := Task.Read_TaskData_min(T_task_id, Average_H.T_sn, Average_H.T_id, 开始时间, 结束时间)
  1104. c.SetAverageShiftedDownward(T_task_id, Average_H.T_id, T_deviation, 目标originalAvg, RoundToDecimal(Average_H.Average, 1), T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "")
  1105. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "" +
  1106. " 温湿度绑定点1 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " +
  1107. " 温湿度绑定点2 平均值:" + lib.To_string(温湿度绑定点2vga) + "℃ " +
  1108. " 测点 平均值" + lib.To_string(originalAvg) + "℃ " +
  1109. " 测点 最优平均值" + lib.To_string(目标originalAvg) + "℃ " +
  1110. " 数据偏差: " + lib.To_string(RoundToDecimal(originalAvg-目标originalAvg, 1)) + "℃ " +
  1111. " 设置:" + lib.To_string(T_deviation) + "℃" +
  1112. " 冷点:" + Average_H.T_id})
  1113. originalAvg = Task.Read_TaskData_Average(Task_r.T_task_id, snList, 开始时间, 结束时间)
  1114. originalAvg = RoundToDecimal(originalAvg, 1)
  1115. i++
  1116. }
  1117. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "" +
  1118. " 温湿度绑定点1 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " +
  1119. " 温湿度绑定点2 平均值:" + lib.To_string(温湿度绑定点2vga) + "℃ " +
  1120. " 测点 平均值" + lib.To_string(originalAvg) + "℃ " +
  1121. " 数据偏差: " + lib.To_string(RoundToDecimal(RoundToDecimal(originalAvg-目标originalAvg, 1), 1)) + "℃ " +
  1122. " 设置:" + lib.To_string(T_deviation) + "℃" +
  1123. " 符合要求!"})
  1124. }
  1125. }
  1126. }
  1127. // 温控传感器绑定点 与 柜内所有测点|箱内所有测点|均匀性布点和产品存放区域测点 对比 ±1
  1128. T_deviation = 1
  1129. 温控传感器绑定点_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "温控传感器绑定点1|温控传感器绑定点2")
  1130. if len(温控传感器绑定点_list) == 0 {
  1131. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "没有找到温控传感器绑定点!"})
  1132. }
  1133. for i, classList := range 温控传感器绑定点_list {
  1134. 温控传感器绑定点OriginalAvg := Task.Read_TaskData_Average(Task_r.T_task_id, classList.T_sn, 开始时间, 结束时间)
  1135. 温控传感器绑定点OriginalAvg = RoundToDecimal(温控传感器绑定点OriginalAvg, 1)
  1136. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "------ 进行 温控传感器绑定点" + strconv.Itoa(i+1) + " 平均值处理 ------"})
  1137. if (温控传感器绑定点OriginalAvg >= originalAvg && 温控传感器绑定点OriginalAvg <= originalAvg+T_deviation) || (温控传感器绑定点OriginalAvg <= originalAvg && 温控传感器绑定点OriginalAvg >= originalAvg-T_deviation) {
  1138. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: " 温控传感器绑定点" + lib.To_string(i+1) + " 平均值:" + lib.To_string(温控传感器绑定点OriginalAvg) + "℃ " +
  1139. " 测点平均值" + lib.To_string(originalAvg) + "℃ " +
  1140. " 数据偏差: " + lib.To_string(RoundToDecimal(math.Abs(温控传感器绑定点OriginalAvg-originalAvg), 1)) + "℃ " +
  1141. " 设置:" + lib.To_string(T_deviation) + "℃" +
  1142. " 符合要求!"})
  1143. } else {
  1144. // 平均值最低点向上偏移
  1145. if 温控传感器绑定点OriginalAvg < originalAvg-T_deviation {
  1146. T_max := Task.Read_TaskData_max(T_task_id, classList.T_sn, classList.T_id, 开始时间, 结束时间)
  1147. T_min := Task.Read_TaskData_min(T_task_id, classList.T_sn, classList.T_id, 开始时间, 结束时间)
  1148. c.SetAverageShiftedUpward(T_task_id, classList.T_id, T_deviation, RoundToDecimal(originalAvg-T_deviation, 1), 温控传感器绑定点OriginalAvg, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "")
  1149. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "温控传感器绑定点" + lib.To_string(i+1) + "" +
  1150. " 平均值:" + lib.To_string(温控传感器绑定点OriginalAvg) + "℃ " +
  1151. "测点平均值" + lib.To_string(originalAvg) + "℃ " +
  1152. "数据偏差: " + lib.To_string(RoundToDecimal(温控传感器绑定点OriginalAvg-(originalAvg-T_deviation), 1)) + "℃ " +
  1153. "设置:" + lib.To_string(T_deviation) + "℃" +
  1154. "温控传感器绑定点平均值向上偏移"})
  1155. continue
  1156. }
  1157. // 向下偏移
  1158. if 温控传感器绑定点OriginalAvg > originalAvg+T_deviation {
  1159. // 热点向下偏移到高点范围
  1160. T_max := Task.Read_TaskData_max(T_task_id, classList.T_sn, classList.T_id, 开始时间, 结束时间)
  1161. T_min := Task.Read_TaskData_min(T_task_id, classList.T_sn, classList.T_id, 开始时间, 结束时间)
  1162. c.SetAverageShiftedDownward(T_task_id, classList.T_id, T_deviation, RoundToDecimal(originalAvg+T_deviation, 1), 温控传感器绑定点OriginalAvg, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "")
  1163. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "温控传感器绑定点" + lib.To_string(i+1) + "" +
  1164. " 平均值:" + lib.To_string(温控传感器绑定点OriginalAvg) + "℃ " +
  1165. "测点平均值" + lib.To_string(originalAvg) + "℃ " +
  1166. "数据偏差: " + lib.To_string(RoundToDecimal(温控传感器绑定点OriginalAvg-(originalAvg+T_deviation), 1)) + "℃ " +
  1167. "设置:" + lib.To_string(T_deviation) + "℃" +
  1168. "温控传感器绑定点平均值向下偏移"})
  1169. }
  1170. }
  1171. }
  1172. // ----------恢复保留数据------------
  1173. if Task_r.T_device_type != "X" {
  1174. c.SaveRetainData(Task_r, 部点终端_list, valueStrings1, valueStrings2, 开空开, 保空开, 开空开驼峰, 保空开驼峰, 温度控制范围最高值, 60)
  1175. } else {
  1176. c.SaveBWXRetainData(Task_r, 部点终端_list, BWXValueStrings, 结束时间, 趋势时间, 60)
  1177. }
  1178. // ----------恢复保留数据结束------------
  1179. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "完成!"})
  1180. // Close the connection
  1181. c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
  1182. }
  1183. /*
  1184. 平均值下移
  1185. targetAvg 参考平均值
  1186. originalAvg 原始平均值
  1187. T_min 整段数据最小值
  1188. T_max 整段数据最大值
  1189. minLimit 温度控制范围最小值
  1190. maxLimit 温度控制范围最大值
  1191. */
  1192. func (c *TaskDataHandleController) SetAverageShiftedDownward(T_task_id, T_id string, T_deviation, targetAvg, originalAvg, T_min, T_max, minLimit, maxLimit float64, StartTime, EndTime string) {
  1193. 目标avg := RoundToDecimal(targetAvg+T_deviation, 1)
  1194. vgaca := RoundToDecimal(originalAvg-目标avg, 1)
  1195. //向下偏移后整段数据最小值大于温度控制范围最小值
  1196. if RoundToDecimal(T_min-vgaca, 1) > RoundToDecimal(minLimit, 1) && RoundToDecimal(T_max-vgaca, 1) < RoundToDecimal(maxLimit, 1) {
  1197. Task.UpdateTaskDataTemperatureAndHumidityByGeometricAVG(T_task_id, T_id, "", "", -vgaca)
  1198. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" +
  1199. " 测点 " + lib.To_string(T_id) +
  1200. " 最大值:" + lib.To_string(T_max) + "℃ " +
  1201. " 最小值:" + lib.To_string(T_min) + "℃ " +
  1202. " 参考平均值:" + lib.To_string(RoundToDecimal(targetAvg, 1)) + "℃ " +
  1203. " 原始平均值:" + lib.To_string(RoundToDecimal(originalAvg, 1)) + "℃ " +
  1204. " 数据偏差:" + lib.To_string(vgaca) + "℃ " +
  1205. " 向下偏移:" + lib.To_string(vgaca) + "℃ "})
  1206. } else {
  1207. var err error
  1208. var compress float64
  1209. compress, vgaca, err = GetLinearTransformationValue(目标avg, originalAvg, T_min, T_max, minLimit, maxLimit)
  1210. if err != nil {
  1211. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "进行处理 数据!" +
  1212. " 测点" + lib.To_string(T_id) +
  1213. " 最大值:" + lib.To_string(T_max) + "℃ " +
  1214. " 最小值:" + lib.To_string(T_min) + "℃ " +
  1215. " 参考平均值:" + lib.To_string(RoundToDecimal(targetAvg, 1)) + "℃ " +
  1216. " 原始平均值:" + lib.To_string(RoundToDecimal(originalAvg, 1)) + "℃ " +
  1217. " 无合法解: 无法满足所有约束条件!"})
  1218. return
  1219. }
  1220. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" +
  1221. " 测点" + lib.To_string(T_id) +
  1222. " 最大值:" + lib.To_string(T_max) + "℃ " +
  1223. " 最小值:" + lib.To_string(T_min) + "℃ " +
  1224. " 参考平均值:" + lib.To_string(RoundToDecimal(targetAvg, 1)) + "℃ " +
  1225. " 原始平均值:" + lib.To_string(RoundToDecimal(originalAvg, 1)) + "℃ " +
  1226. " 缩放:" + lib.To_string(compress) +
  1227. " 缩放后最大值:" + lib.To_string(RoundToDecimal(T_max*compress, 1)) + "℃ " +
  1228. " 缩放后最小值:" + lib.To_string(RoundToDecimal(T_min*compress, 1)) + "℃ " +
  1229. " 数据偏差:" + lib.To_string(vgaca) + "℃ " +
  1230. " 偏移:" + lib.To_string(vgaca) + "℃ "})
  1231. // 压缩
  1232. Task.UpdateTaskDataTemperatureAndHumidityByGeometric_id(T_task_id, T_id, "", "", compress)
  1233. // 偏移
  1234. if vgaca != 0 {
  1235. Task.UpdateTaskDataTemperatureAndHumidityByGeometricAVG(T_task_id, T_id, "", "", vgaca)
  1236. }
  1237. }
  1238. }
  1239. func GetLinearTransformationValue(targetAvg, originalAvg, T_min, T_max, minLimit, maxLimit float64) (float64, float64, error) {
  1240. //var vgaca float64
  1241. //compress1 := RoundToDecimal((minLimit+0.3-targetAvg)/(T_min-originalAvg), 1)
  1242. //compress2 := RoundToDecimal((maxLimit-0.3-targetAvg)/(T_max-originalAvg), 1)
  1243. //compress := math.Min(compress1, compress2)
  1244. //if RoundToDecimal(T_max*compress, 1) < RoundToDecimal(maxLimit, 1) && RoundToDecimal(T_min*compress, 1) > RoundToDecimal(minLimit, 1) {
  1245. // vgaca = 0
  1246. //} else {
  1247. // vgaca = RoundToDecimal(targetAvg-compress*originalAvg, 1)
  1248. //}
  1249. //for _, x := range []float64{T_min, T_max} {
  1250. // newVal := RoundToDecimal(compress*x+vgaca, 1)
  1251. // if newVal < minLimit || newVal > maxLimit {
  1252. // return 0, 0, errors.New("无合法解: 无法满足所有约束条件")
  1253. // }
  1254. //}
  1255. //
  1256. //return compress, vgaca, nil
  1257. minLimit = RoundToDecimal(minLimit+0.2, 1)
  1258. maxLimit = RoundToDecimal(maxLimit-0.2, 1)
  1259. // 策略1: 使用最小边界值 (使变换后最小值 = minBound)
  1260. k1 := (targetAvg - minLimit) / (originalAvg - T_min)
  1261. b1 := minLimit - k1*T_min
  1262. valid1 := true
  1263. for _, x := range []float64{T_min, T_max} {
  1264. newVal := RoundToDecimal(k1*x+b1, 1)
  1265. if newVal < minLimit || newVal > maxLimit {
  1266. valid1 = false
  1267. break
  1268. }
  1269. }
  1270. // 策略2: 使用最大边界值 (使变换后最大值 = maxBound),策略1失败时使用
  1271. k2 := float64(0)
  1272. b2 := float64(0)
  1273. valid2 := false
  1274. if !valid1 {
  1275. k2 = (maxLimit - targetAvg) / (T_max - originalAvg)
  1276. b2 = targetAvg - k2*originalAvg
  1277. valid2 = true
  1278. for _, x := range []float64{T_min, T_max} {
  1279. newVal := RoundToDecimal(k2*x+b2, 1)
  1280. if newVal < minLimit || newVal > maxLimit {
  1281. valid2 = false
  1282. break
  1283. }
  1284. }
  1285. }
  1286. // 根据结果选择有效策略
  1287. switch {
  1288. case valid1:
  1289. return k1, b1, nil
  1290. case valid2:
  1291. return k2, b2, nil
  1292. default:
  1293. return 0, 0, errors.New("无合法解: 无法满足所有约束条件")
  1294. }
  1295. }
  1296. /*
  1297. 平均值上移
  1298. targetAvg 参考平均值
  1299. originalAvg 原始平均值
  1300. T_min 整段数据最小值
  1301. T_max 整段数据最大值
  1302. minLimit 温度控制范围最小值
  1303. maxLimit 温度控制范围最大值
  1304. */
  1305. func (c *TaskDataHandleController) SetAverageShiftedUpward(T_task_id, T_id string, T_deviation, targetAvg, originalAvg, T_min, T_max, minLimit, maxLimit float64, StartTime, EndTime string) {
  1306. 目标avg := RoundToDecimal(targetAvg-T_deviation, 1)
  1307. vgaca := RoundToDecimal(目标avg-originalAvg, 1)
  1308. if RoundToDecimal(T_max+vgaca, 1) < RoundToDecimal(maxLimit, 1) && RoundToDecimal(T_min+vgaca, 1) > RoundToDecimal(minLimit, 1) {
  1309. Task.UpdateTaskDataTemperatureAndHumidityByGeometricAVG(T_task_id, T_id, "", "", vgaca)
  1310. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" +
  1311. " 测点 " + lib.To_string(T_id) +
  1312. " 最大值:" + lib.To_string(T_max) + "℃ " +
  1313. " 最小值:" + lib.To_string(T_min) + "℃ " +
  1314. " 参考平均值:" + lib.To_string(RoundToDecimal(targetAvg, 1)) + "℃ " +
  1315. " 原始平均值:" + lib.To_string(RoundToDecimal(originalAvg, 1)) + "℃ " +
  1316. " 数据偏差:" + lib.To_string(vgaca) + "℃ " +
  1317. " 向上偏移:" + lib.To_string(vgaca) + "℃ "})
  1318. } else {
  1319. var err error
  1320. var compress float64
  1321. compress, vgaca, err = GetLinearTransformationValue(目标avg, originalAvg, T_min, T_max, minLimit, maxLimit)
  1322. if err != nil {
  1323. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "进行处理 数据!" +
  1324. " 测点" + lib.To_string(T_id) +
  1325. " 最大值:" + lib.To_string(T_max) + "℃ " +
  1326. " 最小值:" + lib.To_string(T_min) + "℃ " +
  1327. " 参考平均值:" + lib.To_string(RoundToDecimal(targetAvg, 1)) + "℃ " +
  1328. " 原始平均值:" + lib.To_string(RoundToDecimal(originalAvg, 1)) + "℃ " +
  1329. " 无合法解: 无法满足所有约束条件!"})
  1330. return
  1331. }
  1332. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" +
  1333. " 测点" + lib.To_string(T_id) +
  1334. " 最大值:" + lib.To_string(T_max) + "℃ " +
  1335. " 最小值:" + lib.To_string(T_min) + "℃ " +
  1336. " 参考平均值:" + lib.To_string(RoundToDecimal(targetAvg, 1)) + "℃ " +
  1337. " 原始平均值:" + lib.To_string(RoundToDecimal(originalAvg, 1)) + "℃ " +
  1338. " 缩放:" + lib.To_string(compress) +
  1339. " 缩放后最大值:" + lib.To_string(RoundToDecimal(T_max*compress, 1)) + "℃ " +
  1340. " 缩放后最小值:" + lib.To_string(RoundToDecimal(T_min*compress, 1)) + "℃ " +
  1341. " 数据偏差:" + lib.To_string(vgaca) + "℃ " +
  1342. " 偏移:" + lib.To_string(vgaca) + "℃ "})
  1343. // 压缩
  1344. Task.UpdateTaskDataTemperatureAndHumidityByGeometric_id(T_task_id, T_id, "", "", compress)
  1345. // 偏移
  1346. if vgaca != 0 {
  1347. Task.UpdateTaskDataTemperatureAndHumidityByGeometricAVG(T_task_id, T_id, "", "", vgaca)
  1348. }
  1349. }
  1350. }
  1351. func (c *TaskDataHandleController) GetCalculateHumps(T_task_id string, SN_list []Device.DeviceClassList, startTime, types string) (calculateHumps Task.CalculateHumps_R) {
  1352. SN := Device.JoinDeviceClassListSnToString(SN_list)
  1353. var is bool
  1354. calculateHumps, is = Task.Redis_CalculateHumps_Get(T_task_id + types)
  1355. if !is {
  1356. list := Task.Read_TaskData_ById_AVG(T_task_id, SN, startTime, "")
  1357. // 获取第一个驼峰结束时间点
  1358. CalculateHumps_list := Task.CalculateHumpsByThreeDots(list)
  1359. if len(CalculateHumps_list) < 1 {
  1360. return
  1361. }
  1362. calculateHumps = CalculateHumps_list[0]
  1363. Task.Redis_CalculateHumps_Set(T_task_id+types, calculateHumps)
  1364. }
  1365. return calculateHumps
  1366. }
  1367. func (c *TaskDataHandleController) GetMetadata(T_task_id string, SN_list []Device.DeviceClassList, startTime, types string) (valueStrings []string, calculateHumps Task.CalculateHumps_R) {
  1368. SN := Device.JoinDeviceClassListSnToString(SN_list)
  1369. var is bool
  1370. calculateHumps, is = Task.Redis_CalculateHumps_Get(T_task_id + types)
  1371. if !is {
  1372. return
  1373. }
  1374. endTime := calculateHumps.End.T_time
  1375. data1, _ := Task.Read_TaskData_ById_List_AES(T_task_id, SN, "", startTime, endTime, 0, 9999)
  1376. for _, v := range data1 {
  1377. 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))
  1378. }
  1379. return valueStrings, calculateHumps
  1380. }
  1381. func (c *TaskDataHandleController) GetCalculateHumpsMaps(T_task_id string, SN_list []Device.DeviceClassList, startTime string) map[string]Task.CalculateHumps_R {
  1382. var CalculateHumpsMaps = make(map[string]Task.CalculateHumps_R)
  1383. SN := Device.JoinDeviceClassListSnToString(SN_list)
  1384. allList := Task.Read_TaskData_ById_AVG(T_task_id, SN, startTime, "")
  1385. // 获取第一个驼峰结束时间点
  1386. CalculateHumps_list := Task.CalculateHumpsByThreeDots(allList)
  1387. if len(CalculateHumps_list) < 1 {
  1388. return CalculateHumpsMaps
  1389. }
  1390. for _, device := range SN_list {
  1391. list := Task.Read_TaskData_ById_AVG(T_task_id, device.T_sn, startTime, "")
  1392. //获取第一个驼峰结束时间点
  1393. CalculateHumps := Task.CalculateHumpsByThreeDots(list)
  1394. if len(CalculateHumps) < 1 {
  1395. CalculateHumpsMaps[device.T_sn] = CalculateHumps_list[0]
  1396. continue
  1397. }
  1398. if CalculateHumps[0].Peak.T_time != CalculateHumps_list[0].Peak.T_time {
  1399. CalculateHumps[0].Peak.T_time = CalculateHumps_list[0].Peak.T_time
  1400. }
  1401. et1, _ := lib.TimeStrToTime(CalculateHumps_list[0].End.T_time)
  1402. et2, _ := lib.TimeStrToTime(CalculateHumps[0].End.T_time)
  1403. if et1.Before(et2) {
  1404. CalculateHumps[0].End.T_time = CalculateHumps_list[0].End.T_time
  1405. }
  1406. CalculateHumpsMaps[device.T_sn] = CalculateHumps[0]
  1407. }
  1408. return CalculateHumpsMaps
  1409. }
  1410. // 获取保留数据
  1411. func (c *TaskDataHandleController) GetRetainData(Task_r Task.Task, SN_list []Device.DeviceClassList, useCache bool) (valueStrings1, valueStrings2 []string,
  1412. kkkStartTime, bkkStartTime string, kkkCalculateHumps, bkkCalculateHumps Task.CalculateHumps_R) {
  1413. var 开空开, 保空开 string
  1414. var 开空开驼峰, 保空开驼峰 Task.CalculateHumps_R
  1415. if Task_r.T_device_type != "X" {
  1416. 开空开 = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "开空开")
  1417. if len(开空开) == 0 {
  1418. 开空开 = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "开满开")
  1419. }
  1420. if len(开空开) == 0 {
  1421. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 开空开/开满开 时间 标签!"})
  1422. return
  1423. }
  1424. //保空开 = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "保空开")
  1425. //if len(保空开) == 0 {
  1426. // 保空开 = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "保满开")
  1427. //}
  1428. //if len(保空开) == 0 {
  1429. // lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 保空开/保满开 时间 标签!"})
  1430. // return
  1431. //}
  1432. //if !useCache {
  1433. // 开空开驼峰 = c.GetCalculateHumps(Task_r.T_task_id, SN_list, 开空开, "kkk")
  1434. // 保空开驼峰 = c.GetCalculateHumps(Task_r.T_task_id, SN_list, 保空开, "bkk")
  1435. //}
  1436. //
  1437. //valueStrings1, 开空开驼峰 = c.GetMetadata(Task_r.T_task_id, SN_list, 开空开, "kkk")
  1438. //valueStrings2, 保空开驼峰 = c.GetMetadata(Task_r.T_task_id, SN_list, 保空开, "bkk")
  1439. SN := Device.JoinDeviceClassListSnToString(SN_list)
  1440. data1, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, SN, "", 开空开, "", 0, 9999)
  1441. for _, v := range data1 {
  1442. valueStrings1 = append(valueStrings1, fmt.Sprintf("('%s','%s',%v,%v,'%s')", v.T_sn, v.T_id, v.T_t, v.T_rh, v.T_time))
  1443. }
  1444. }
  1445. return valueStrings1, valueStrings2, 开空开, 保空开, 开空开驼峰, 保空开驼峰
  1446. }
  1447. // 获取保留数据
  1448. func (c *TaskDataHandleController) SaveRetainData(Task_r Task.Task, SN_list []Device.DeviceClassList, valueStrings1, valueStrings2 []string,
  1449. kkkStartTime, bkkStartTime string, kkkCalculateHumps, bkkCalculateHumps Task.CalculateHumps_R, maxLimit float64, saveTime int) {
  1450. var err error
  1451. if len(valueStrings1) > 0 {
  1452. //将开空开/开满开时间开始第一个驼峰 写入原始数据
  1453. //将 开空开/开满开时间 后时间写入原始数据
  1454. SN := Device.JoinDeviceClassListSnToString(SN_list)
  1455. Task.DeleteTaskAllDataByTimeRange(Task_r.T_task_id, SN, kkkStartTime, kkkCalculateHumps.End.T_time)
  1456. err = Task.Batch_Adds_TaskData(Task_r.T_task_id, valueStrings1)
  1457. if err == nil {
  1458. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: fmt.Sprintf("恢复 开空开/开满开 时间点后驼峰 %s ~ %s 数据 %d/%d", kkkStartTime, kkkCalculateHumps.End.T_time, len(valueStrings1), len(valueStrings1))})
  1459. }
  1460. }
  1461. if len(valueStrings2) > 0 {
  1462. //将开空开/开满开时间开始第一个驼峰 写入原始数据
  1463. SN := Device.JoinDeviceClassListSnToString(SN_list)
  1464. Task.DeleteTaskAllDataByTimeRange(Task_r.T_task_id, SN, bkkStartTime, bkkCalculateHumps.End.T_time)
  1465. err = Task.Batch_Adds_TaskData(Task_r.T_task_id, valueStrings2)
  1466. if err == nil {
  1467. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: fmt.Sprintf("恢复 保空开/保满开 时间点后驼峰 %s ~ %s 数据 %d/%d", kkkStartTime, kkkCalculateHumps.End.T_time, len(valueStrings1), len(valueStrings1))})
  1468. }
  1469. }
  1470. //c.SaveRetainDataAndTrend(Task_r, SN_list, valueStrings1, kkkStartTime, kkkCalculateHumps, maxLimit, saveTime)
  1471. //c.SaveRetainDataAndTrend(Task_r, SN_list, valueStrings2, bkkStartTime, bkkCalculateHumps, maxLimit, saveTime)
  1472. }
  1473. // 获取保留数据
  1474. func (c *TaskDataHandleController) SaveRetainDataTrend(Task_r Task.Task, SN_list []Device.DeviceClassList, valueStrings1, valueStrings2 []string,
  1475. kkkStartTime, bkkStartTime string, kkkCalculateHumps, bkkCalculateHumps Task.CalculateHumps_R, maxLimit float64, saveTime int) {
  1476. c.SaveRetainDataAndTrend(Task_r, SN_list, valueStrings1, kkkStartTime, kkkCalculateHumps, maxLimit, saveTime)
  1477. c.SaveRetainDataAndTrend(Task_r, SN_list, valueStrings2, bkkStartTime, bkkCalculateHumps, maxLimit, saveTime)
  1478. }
  1479. func (c *TaskDataHandleController) SaveRetainDataAndTrend(Task_r Task.Task, SN_list []Device.DeviceClassList, valueStrings1 []string,
  1480. kkkStartTime string, kkkCalculateHumps Task.CalculateHumps_R, maxLimit float64, saveTime int) {
  1481. var err error
  1482. if len(valueStrings1) > 0 {
  1483. //将开空开/开满开时间开始第一个驼峰 写入原始数据
  1484. SN := Device.JoinDeviceClassListSnToString(SN_list)
  1485. Task.DeleteTaskAllDataByTimeRange(Task_r.T_task_id, SN, kkkStartTime, kkkCalculateHumps.End.T_time)
  1486. err = Task.Batch_Adds_TaskData(Task_r.T_task_id, valueStrings1)
  1487. if err == nil {
  1488. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: fmt.Sprintf("恢复 开空开/开满开 保空开/保满开 时间点后驼峰 %s ~ %s 数据 %d/%d", kkkStartTime, kkkCalculateHumps.End.T_time, len(valueStrings1), len(valueStrings1))})
  1489. }
  1490. startTimeT, _ := lib.TimeStrToTime(kkkStartTime)
  1491. startTime := startTimeT.Add(-time.Minute).Format("2006-01-02 15:04")
  1492. endTimeT, _ := lib.TimeStrToTime(kkkCalculateHumps.End.T_time)
  1493. endTime := endTimeT.Add(time.Minute).Format("2006-01-02 15:04")
  1494. // 执行数据平滑
  1495. for _, v := range SN_list {
  1496. sn := v.T_sn
  1497. id_str := v.T_id
  1498. //AllList, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, sn, id_str, startTime, kkkCalculateHumps.End.T_time, 0, 9999)
  1499. var trendTime, declineTrendTime string
  1500. trendTime = kkkCalculateHumps.Peak.T_time
  1501. declineTrendTime = kkkCalculateHumps.Peak.T_time
  1502. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "执行数据上升趋势"})
  1503. if len(trendTime) > 0 {
  1504. list, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, sn, id_str, startTime, trendTime, 0, 9999)
  1505. if len(list) <= 2 {
  1506. continue
  1507. }
  1508. first := list[0]
  1509. var last Task.TaskData_
  1510. if len(list) > 10 {
  1511. last = list[len(list)-2]
  1512. } else {
  1513. last = list[len(list)-1]
  1514. }
  1515. current, _ := time.Parse("2006-01-02 15:04", first.T_time)
  1516. next, _ := time.Parse("2006-01-02 15:04", last.T_time)
  1517. interval := next.Sub(current).Seconds() / float64(saveTime)
  1518. //ttInterval := (last.T_t - first.T_t) / float32(interval)
  1519. trhInterval := (last.T_rh - first.T_rh) / float32(interval)
  1520. ttList := generateRisingCurve(float64(first.T_t), float64(last.T_t), int(interval+1))
  1521. //tt := first.T_t
  1522. ttrh := first.T_rh
  1523. var valueStrings []string
  1524. for i := 0; i <= int(interval); i++ {
  1525. //tt += ttInterval
  1526. ttrh += trhInterval
  1527. ttime := current.Format("2006-01-02 15:04")
  1528. valueStrings = append(valueStrings, fmt.Sprintf("('%s','%s',%v,%v,'%s')", first.T_sn, id_str, ttList[i], ttrh, ttime))
  1529. current = current.Add(time.Second * time.Duration(saveTime))
  1530. }
  1531. //for current.Unix() <= next.Unix() {
  1532. //
  1533. // tt += ttInterval
  1534. // ttrh += trhInterval
  1535. // ttime := current.Format("2006-01-02 15:04")
  1536. // valueStrings = append(valueStrings, fmt.Sprintf("('%s','%s',%v,%v,'%s')", first.T_sn, id_str, tt, ttrh, ttime))
  1537. // current = current.Add(time.Second * time.Duration(saveTime))
  1538. //}
  1539. Task.DeleteTaskDataByTimeRange(Task_r.T_task_id, sn, id_str, first.T_time, last.T_time)
  1540. Task.Batch_Adds_TaskData(Task_r.T_task_id, valueStrings)
  1541. }
  1542. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "执行数据下降趋势"})
  1543. if len(declineTrendTime) > 0 {
  1544. list, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, sn, id_str, declineTrendTime, endTime, 0, 9999)
  1545. if len(list) <= 2 {
  1546. continue
  1547. }
  1548. if list[len(list)-1].T_t > list[len(list)-2].T_t {
  1549. continue
  1550. }
  1551. var first Task.TaskData_
  1552. if len(list) > 10 {
  1553. first = list[1]
  1554. } else {
  1555. first = list[0]
  1556. }
  1557. last := list[len(list)-1]
  1558. current, _ := time.Parse("2006-01-02 15:04", first.T_time)
  1559. next, _ := time.Parse("2006-01-02 15:04", last.T_time)
  1560. interval := next.Sub(current).Seconds() / float64(saveTime)
  1561. //ttInterval := (last.T_t - first.T_t) / float32(interval)
  1562. trhInterval := (last.T_rh - first.T_rh) / float32(interval)
  1563. ttList := generateTemperatureCurve(float64(first.T_t), float64(last.T_t), int(interval+1))
  1564. //tt := first.T_t
  1565. ttrh := first.T_rh
  1566. var valueStrings []string
  1567. for i := 0; i <= int(interval); i++ {
  1568. //tt += ttInterval
  1569. ttrh += trhInterval
  1570. ttime := current.Format("2006-01-02 15:04")
  1571. valueStrings = append(valueStrings, fmt.Sprintf("('%s','%s',%v,%v,'%s')", first.T_sn, id_str, ttList[i], ttrh, ttime))
  1572. current = current.Add(time.Second * time.Duration(saveTime))
  1573. }
  1574. Task.DeleteTaskDataByTimeRange(Task_r.T_task_id, sn, id_str, first.T_time, last.T_time)
  1575. Task.Batch_Adds_TaskData(Task_r.T_task_id, valueStrings)
  1576. }
  1577. }
  1578. }
  1579. }
  1580. // 获取保留数据
  1581. func (c *TaskDataHandleController) GetBWXRetainData(Task_r Task.Task, SN string, endTime, trendTime string) (BWXValueStrings []string) {
  1582. if endTime != trendTime {
  1583. data1, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, SN, "", trendTime, "", 0, 9999)
  1584. for _, v := range data1 {
  1585. 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))
  1586. }
  1587. }
  1588. return
  1589. }
  1590. func (c *TaskDataHandleController) SaveBWXRetainData(Task_r Task.Task, SN_list []Device.DeviceClassList,
  1591. BWXValueStrings []string, endTime, trendTime string, saveTime int) {
  1592. var err error
  1593. if endTime != trendTime && len(BWXValueStrings) > 0 {
  1594. //将开空开/开满开时间开始第一个驼峰 写入原始数据
  1595. for _, device := range SN_list {
  1596. Task.DeleteTaskDataByTimeRange(Task_r.T_task_id, device.T_sn, device.T_id, trendTime, "")
  1597. }
  1598. err = Task.Batch_Adds_TaskData(Task_r.T_task_id, BWXValueStrings)
  1599. if err == nil {
  1600. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: fmt.Sprintf("恢复 保温箱 原始数据 %d/%d", len(BWXValueStrings), len(BWXValueStrings))})
  1601. }
  1602. var startTime string
  1603. startTime = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "静态开箱作业开箱结束时间")
  1604. if len(startTime) == 0 {
  1605. startTime = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "动态开箱作业开箱结束时间")
  1606. }
  1607. if len(startTime) == 0 {
  1608. startTime = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "开箱作业开箱结束时间")
  1609. }
  1610. if len(startTime) == 0 {
  1611. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 静态开箱作业开箱结束时间|动态开箱作业开箱结束时间|开箱作业开箱结束时间 失败"})
  1612. return
  1613. }
  1614. startTimeT, _ := lib.TimeStrToTime(startTime)
  1615. startTime = startTimeT.Add(30 * time.Minute).Format("2006-01-02 15:04")
  1616. // 执行数据平滑
  1617. for _, v := range SN_list {
  1618. sn := v.T_sn
  1619. id_str := v.T_id
  1620. list, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, sn, id_str, startTime, trendTime, 0, 9999)
  1621. first := list[0]
  1622. last := list[len(list)-1]
  1623. current, _ := time.Parse("2006-01-02 15:04", first.T_time)
  1624. next, _ := time.Parse("2006-01-02 15:04", last.T_time)
  1625. interval := next.Sub(current).Seconds() / float64(saveTime)
  1626. ttInterval := (last.T_t - first.T_t) / float32(interval)
  1627. trhInterval := (last.T_rh - first.T_rh) / float32(interval)
  1628. tt := first.T_t
  1629. ttrh := first.T_rh
  1630. var valueStrings []string
  1631. for current.Unix() <= next.Unix() {
  1632. tt += ttInterval
  1633. ttrh += trhInterval
  1634. ttime := current.Format("2006-01-02 15:04")
  1635. valueStrings = append(valueStrings, fmt.Sprintf("('%s','%s',%v,%v,'%s')", first.T_sn, id_str, tt, ttrh, ttime))
  1636. current = current.Add(time.Second * time.Duration(saveTime))
  1637. }
  1638. Task.DeleteTaskDataByTimeRange(Task_r.T_task_id, sn, id_str, startTime, trendTime)
  1639. err = Task.Batch_Adds_TaskData(Task_r.T_task_id, valueStrings)
  1640. if err == nil {
  1641. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: fmt.Sprintf("保温箱数据趋势 %d/%d", len(valueStrings), len(valueStrings))})
  1642. }
  1643. }
  1644. }
  1645. }
  1646. // 获取开始结束时间
  1647. func (c *TaskDataHandleController) GetStartTimeAndEndTime(Task_r Task.Task, SN string, maxLimit float64) (startTime, endTime, trendTime string) {
  1648. // 开始时间 获取温度下降到第二个低点时间
  1649. // 1. 获取温度平均值
  1650. list := Task.Read_TaskData_ById_AVG(Task_r.T_task_id, SN, "", "")
  1651. if len(list) < 2 {
  1652. lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "均匀性布点+产品存放区域测点+作业出入口总测点 数据平均值 少于2条!"})
  1653. return
  1654. }
  1655. // 找平均值低于温度控制范围最高值的第二个最低点
  1656. lowPoint := 0
  1657. for i := 1; i <= len(list)-2; i++ {
  1658. 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) {
  1659. lowPoint += 1
  1660. }
  1661. if lowPoint == 2 {
  1662. startTime = list[i].T_time
  1663. break
  1664. }
  1665. }
  1666. // 保温箱没有开空开,开满开
  1667. // 结束时间温度超限取没有超限时间点,结束时间温度未超限取最后一个时间点
  1668. if Task_r.T_device_type == "X" {
  1669. list2 := Task.Read_TaskData_ById_AVG_DESC(Task_r.T_task_id, SN, "", "")
  1670. if len(list) == 0 {
  1671. return
  1672. }
  1673. if float64(list2[0].T_t) < maxLimit {
  1674. endTime = list2[0].T_time
  1675. trendTime = list2[0].T_time
  1676. return
  1677. }
  1678. for i, avg := range list2 {
  1679. if RoundToDecimal(float64(avg.T_t), 1) < maxLimit {
  1680. endTime = avg.T_time
  1681. trendTime = list2[i-1].T_time
  1682. break
  1683. }
  1684. }
  1685. } else {
  1686. endTime = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "开空开")
  1687. if len(endTime) == 0 {
  1688. endTime = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "开满开")
  1689. }
  1690. if len(endTime) == 0 {
  1691. endTime = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "现场测试结束时间")
  1692. }
  1693. if len(endTime) == 0 {
  1694. return
  1695. }
  1696. }
  1697. return
  1698. }
  1699. /*
  1700. 计算绑定点的值
  1701. A 监测终端01平均值
  1702. B 监测终端02平均值
  1703. C 温湿度绑定点01平均值
  1704. D 温湿度绑定点02平均值
  1705. */
  1706. func findBindingPointsOptimalAdjustment(A, B, C, D, T_deviation float64) (float64, float64, bool) {
  1707. type DataPair struct {
  1708. A1 float64
  1709. B1 float64
  1710. }
  1711. T_deviation_half := 0.1
  1712. var dataPairs []DataPair
  1713. var A1, B1 float64 = -100, -100
  1714. // 生成A1和B1的可能值
  1715. for a1 := A - T_deviation; a1 <= A+T_deviation; a1 += T_deviation_half {
  1716. for b1 := B - T_deviation; b1 <= B+T_deviation; b1 += T_deviation_half {
  1717. // 检查是否存在满足条件的C值
  1718. minC := math.Max(a1-T_deviation_half, b1-T_deviation_half)
  1719. maxC := math.Min(a1+T_deviation_half, b1+T_deviation_half)
  1720. if minC <= maxC {
  1721. dataPairs = append(dataPairs, DataPair{A1: a1, B1: b1})
  1722. }
  1723. }
  1724. }
  1725. if len(dataPairs) == 1 {
  1726. A1 = dataPairs[0].A1
  1727. B1 = dataPairs[0].B1
  1728. }
  1729. if len(dataPairs) > 1 {
  1730. // 寻找最优解
  1731. minAdjustment := math.MaxFloat64
  1732. var optimalPair DataPair
  1733. for _, pair := range dataPairs {
  1734. adjustment := math.Abs(pair.A1-C) + math.Abs(pair.B1-D)
  1735. if adjustment < minAdjustment {
  1736. minAdjustment = adjustment
  1737. optimalPair = pair
  1738. }
  1739. }
  1740. A1 = optimalPair.A1
  1741. B1 = optimalPair.B1
  1742. }
  1743. if A1 == -100 || B1 == -100 {
  1744. return A1, B1, false
  1745. }
  1746. return A1, B1, true
  1747. }
  1748. /*
  1749. 计算绑定点的值
  1750. A 温湿度绑定点1平均值
  1751. B 温湿度绑定点2平均值
  1752. C 测点平均值
  1753. */
  1754. func findAverageOptimalAdjustment(A, B, C float64) float64 {
  1755. // 计算有效区间
  1756. minA := A - 0.5
  1757. maxA := A + 0.5
  1758. minB := B - 0.5
  1759. maxB := B + 0.5
  1760. // 求交集范围
  1761. lowerBound := math.Max(minA, minB)
  1762. upperBound := math.Min(maxA, maxB)
  1763. // 确定最优调整值
  1764. var optimalC float64
  1765. if C < lowerBound {
  1766. optimalC = lowerBound // 取区间下限
  1767. } else if C > upperBound {
  1768. optimalC = upperBound // 取区间上限
  1769. } else {
  1770. optimalC = C // 已在区间内无需调整
  1771. }
  1772. return optimalC
  1773. }
  1774. func generateTemperatureCurve(startTemp, minTemp float64, steps int) []float64 {
  1775. if steps <= 0 {
  1776. return []float64{}
  1777. }
  1778. // 计算动态参数确保严格递减且高于最低温度
  1779. base := minTemp + 0.1 // 确保所有值高于minTemp
  1780. decayFactor := math.Log((startTemp-base)/(minTemp+0.5-base)) / float64(steps-1)
  1781. temperatures := make([]float64, steps)
  1782. prevTemp := startTemp
  1783. for i := 0; i < steps; i++ {
  1784. // 使用指数衰减模型确保严格单调递减
  1785. temp := base + (startTemp-base)*math.Exp(-decayFactor*float64(i))
  1786. // 确保严格递减且高于最低温度
  1787. if temp >= prevTemp {
  1788. temp = prevTemp - 0.1
  1789. }
  1790. if temp <= minTemp {
  1791. temp = minTemp + 0.01 + 0.05*float64(steps-i)/float64(steps)
  1792. }
  1793. // 保持精度并确保唯一性
  1794. temp = math.Round(temp*100) / 100
  1795. temperatures[i] = temp
  1796. prevTemp = temp
  1797. }
  1798. return temperatures
  1799. }
  1800. func generateRisingCurve(minTemp, maxTemp float64, steps int) []float64 {
  1801. if steps <= 0 {
  1802. return []float64{}
  1803. }
  1804. // 计算动态参数确保严格递增且低于最高温度
  1805. growthFactor := math.Log((maxTemp-minTemp-0.1)/0.1) / float64(steps-1)
  1806. temperatures := make([]float64, steps)
  1807. prevTemp := minTemp
  1808. for i := 0; i < steps; i++ {
  1809. // 使用指数增长模型确保严格单调递增
  1810. temp := minTemp + (maxTemp-minTemp)*(1-math.Exp(-growthFactor*float64(i)))
  1811. // 确保严格递增且低于最高温度
  1812. if temp <= prevTemp {
  1813. temp = prevTemp + 0.1
  1814. }
  1815. if temp >= maxTemp {
  1816. temp = maxTemp - 0.01 - 0.05*float64(steps-i-1)/float64(steps)
  1817. }
  1818. // 保持精度并确保唯一性
  1819. temp = math.Round(temp*100) / 100
  1820. temperatures[i] = temp
  1821. prevTemp = temp
  1822. }
  1823. return temperatures
  1824. }