package controllers import ( "ColdVerify_local/lib" "ColdVerify_local/logs" "ColdVerify_local/models/Device" "ColdVerify_local/models/Task" "ColdVerify_local/models/VerifyTemplate" "fmt" beego "github.com/beego/beego/v2/server/web" "math" "net/http" "strconv" "strings" "time" ) type TaskDataHandleController struct { beego.Controller } /* 同区域数据缺失 */ // 测点自检 自动添加缺失终端,取关联绑定终端平均复制 func (c *TaskDataHandleController) SSE_Automatically_add_missing_terminal() { T_task_id := c.GetString("T_task_id") // v26nplogbwt1 println("T_task_id:", T_task_id) c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream") c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache") c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive") lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "任务开始......"}) Task_r, err := Task.Read_Task(T_task_id) if err != nil { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取任务信息失败!"}) return } DeviceClassList_r := Device.Read_DeviceClassList_List_id_By_Terminal(Task_r.T_class, false) lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "终端总共:" + lib.To_string(len(DeviceClassList_r)) + " 正在检查自检探头..."}) for _, class_ := range DeviceClassList_r { _, cnt := Task.Read_TaskData_ById_List(Task_r.T_task_id, class_.T_sn, class_.T_id, "", "", 0, 1) if cnt == 0 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "找到" + class_.T_id + " " + class_.T_remark + " 自检探头"}) // -----------开始平均复制到 device := Device.DeviceClassList{ T_class: class_.T_class, T_id: class_.T_id, T_sn: class_.T_sn, T_remark: class_.T_remark, } c.SetAdjacentDeviceAVGTaskData(T_task_id, device, "", "") // -----------开始平均复制到结束 } } lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "完成!"}) // Close the connection c.Ctx.ResponseWriter.WriteHeader(http.StatusOK) } // 测点数据自检 自动添加缺失数据,取关联绑定终端平均复制 func (c *TaskDataHandleController) SSE_Automatically_add_missing_data() { T_task_id := c.GetString("T_task_id") // v26nplogbwt1 c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream") c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache") c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive") lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "任务开始......"}) Task_r, err := Task.Read_Task(T_task_id) if err != nil { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取任务信息失败!"}) return } // 时间间隔 s T_saveT := 60 DeviceClassList_list := Device.Read_DeviceClassList_List_id_By_Terminal(Task_r.T_class, false) // 分组统计每个sn的数据数量 snList := Device.JoinDeviceClassListSnToString(DeviceClassList_list) TaskData_Total_GroupBySnId := Task.Read_TaskData_Total_GroupBySnId(Task_r.T_task_id, snList, "", "") if len(TaskData_Total_GroupBySnId) == 0 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "暂无测点需要自检!"}) } Devicedata_list_MAX := TaskData_Total_GroupBySnId[0].Total TaskData_Total_GroupBySnId_Map := make(map[string]int64) for _, v := range TaskData_Total_GroupBySnId { TaskData_Total_GroupBySnId_Map[v.T_sn] = v.Total } 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, "", "") logs.Println("数据标准数量:", Devicedata_list_MAX) // 选择 数据缺失的终端 for _, DeviceClassList_r := range DeviceClassList_list { total, ok := TaskData_Total_GroupBySnId_Map[DeviceClassList_r.T_sn] if !ok { // 测点自检事再处理 lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: DeviceClassList_r.T_id + " 终端自检数据 , 测点缺失,跳过"}) continue } if Devicedata_list_MAX == total { continue } list, cnt := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, DeviceClassList_r.T_sn, DeviceClassList_r.T_id, "", "", 0, 9999) lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: DeviceClassList_r.T_id + " 终端自检数据 ,数据差值:" + lib.To_string(Devicedata_list_MAX-cnt) + " "}) // 开始结束时间不同,直接执行平均复制到 if startTime != list[0].T_time || endTime != list[len(list)-1].T_time { if Devicedata_list_MAX-cnt != 1 { // -----------开始平均复制到 device := Device.DeviceClassList{ T_class: DeviceClassList_r.T_class, T_id: DeviceClassList_r.T_id, T_sn: DeviceClassList_r.T_sn, T_remark: DeviceClassList_r.T_remark, } c.SetAdjacentDeviceAVGTaskData(T_task_id, device, "", "") // -----------开始平均复制到结束 continue } else { if startTime != list[0].T_time { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: DeviceClassList_r.T_id + " 找到到自检时间点 " + startTime + " ~ " + list[0].T_time + " 开始自检"}) Task.InsertTaskData(Task_r.T_task_id, Task.TaskData_{ T_sn: list[0].T_sn, T_id: list[0].T_id, T_t: list[0].T_t, T_rh: list[0].T_rh, T_time: startTime, }) continue } if endTime != list[len(list)-1].T_time { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: DeviceClassList_r.T_id + " 找到自检时间点 " + list[len(list)-1].T_time + " ~ " + endTime + " 开始自检"}) Task.InsertTaskData(Task_r.T_task_id, Task.TaskData_{ T_sn: list[len(list)-1].T_sn, T_id: list[len(list)-1].T_id, T_t: list[len(list)-1].T_t, T_rh: list[len(list)-1].T_rh, T_time: endTime, }) continue } } } for i := 0; i < len(list)-1; i++ { current := list[i].T_time next := list[i+1].T_time ct, _ := time.Parse("2006-01-02 15:04:05", current) nt, _ := time.Parse("2006-01-02 15:04:05", next) interval := nt.Unix() - ct.Unix() //logs.Debug("时间间隔:", interval, "保存时间:", saveTime) //fmt.Println("当前:", current, "下一个:", next) // 缺一个时间点 补漏 if int(interval) == 2*T_saveT { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: list[i].T_id + " 找到自检时间点 " + current + " ~ " + next + " 开始自检"}) t := ct.Add(time.Second * time.Duration(T_saveT)).Format("2006-01-02 15:04") //时间临时变量 ttt := (list[i].T_t + list[i+1].T_t) / 2 trht := (list[i].T_rh + list[i+1].T_rh) / 2 Task.InsertTaskData(Task_r.T_task_id, Task.TaskData_{ T_sn: list[i].T_sn, T_id: list[i].T_id, T_t: ttt, T_rh: trht, T_time: t, }) continue } // 缺的数据大于一个时间点,执行平均复制到 if int(interval) > T_saveT { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: list[i].T_id + " 找到自检时间点 " + current + " ~ " + next + " 开始自检"}) // -----------开始平均复制到 device := Device.DeviceClassList{ T_class: DeviceClassList_r.T_class, T_id: DeviceClassList_r.T_id, T_sn: DeviceClassList_r.T_sn, T_remark: DeviceClassList_r.T_remark, } c.SetAdjacentDeviceAVGTaskData(T_task_id, device, "", "") // -----------开始平均复制到结束 // 平均复制结束,跳出循环 break } } } lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "完成!"}) // Close the connection c.Ctx.ResponseWriter.WriteHeader(http.StatusOK) } // 数据持续时间 x 分钟 没有变化 func (c *TaskDataHandleController) SSE_Continuously_unchanged_data() { T_task_id := c.GetString("T_task_id") // v26nplogbwt1 T_timeout, _ := c.GetInt("T_timeout", 30) // 持续时间 c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream") c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache") c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive") lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "任务开始......"}) Task_r, err := Task.Read_Task(T_task_id) if err != nil { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取任务信息失败!"}) return } // 获取 备注 下面关联设备,数量 DeviceClassList_list := Device.Read_DeviceClassList_List_id_By_Terminal(Task_r.T_class, false) // 选择 数据缺失的终端 var DeleteDeviceClassList []Device.DeviceClassList for _, DeviceClassList_r := range DeviceClassList_list { TaskData_list, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, DeviceClassList_r.T_sn, DeviceClassList_r.T_id, "", "", 0, 9999) if len(TaskData_list) == 0 { continue } maxCount, start, end := Task.FindUnchangedInterval(TaskData_list) if strings.Contains(DeviceClassList_r.T_remark, "保温箱外环境测点") || strings.Contains(DeviceClassList_r.T_remark, "冷藏库作业口外部环境测点") || strings.Contains(DeviceClassList_r.T_remark, "冷藏库外部环境测点") || strings.Contains(DeviceClassList_r.T_remark, "冷藏柜外部环境测点") || strings.Contains(DeviceClassList_r.T_remark, "冷藏车外部环境测点") || strings.Contains(DeviceClassList_r.T_remark, "仓库室外测点") { continue } if maxCount > T_timeout { Task.DeleteTaskDataByTimeRange(T_task_id, DeviceClassList_r.T_sn, DeviceClassList_r.T_id, "", "") DeleteDeviceClassList = append(DeleteDeviceClassList, DeviceClassList_r) lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "找到" + DeviceClassList_r.T_id + " 探头, " + "最多连续 " + lib.To_string(maxCount) + " 分钟没有变化," + "开始时间:" + start + " 结束时间:" + end + "," + "开始自检"}) } } for _, class_ := range DeleteDeviceClassList { // -----------开始平均复制到 device := Device.DeviceClassList{ T_class: class_.T_class, T_id: class_.T_id, T_sn: class_.T_sn, T_remark: class_.T_remark, } c.SetAdjacentDeviceAVGTaskData(T_task_id, device, "", "") // -----------开始平均复制到结束 } lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "完成!"}) // Close the connection c.Ctx.ResponseWriter.WriteHeader(http.StatusOK) } // 区间数据校正 (布点区域数据自检) 均匀性布点,产品存放区域测点 区间数据超标校正 超标数据偏移到区间内 func (c *TaskDataHandleController) SSE_Interval_data_correction() { T_task_id := c.GetString("T_task_id") // v26nplogbwt1 c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream") c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache") c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive") lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "任务开始......"}) Task_r, err := Task.Read_Task(T_task_id) if err != nil { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取任务信息失败!"}) return } 温度控制范围最小值 := float64(lib.To_float32(VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "温度控制范围最小值"))) 温度控制范围最高值 := float64(lib.To_float32(VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "温度控制范围最高值"))) if 温度控制范围最小值 == 0 || 温度控制范围最高值 == 0 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温度控制范围 标签值不正确!"}) return } // 均匀性布点 产品存放区域测点 部点终端_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "均匀性布点|产品存放区域测点|作业出入口总测点") if len(部点终端_list) <= 2 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "均匀性布点|产品存放区域测点|作业出入口总测点 太少了,至少两条以上!"}) return } 部点终端_sn_list := Device.JoinDeviceClassListSnToString(部点终端_list) var 开始时间, 结束时间, 趋势时间 string 开始时间, 结束时间, 趋势时间 = c.GetStartTimeAndEndTime(Task_r, 部点终端_sn_list, 温度控制范围最高值) if 开始时间 == "" || 结束时间 == "" { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 开始时间 或 结束时间 结束时间!"}) return } type AVGClassList struct { T_sn string T_id string T_max float64 T_min float64 T_diff float64 // 最大最小值差异 } fmt.Println("数据准备:", 开始时间, 结束时间, 温度控制范围最小值, 温度控制范围最高值) // -------------------- 温湿度绑定点vga_H -------------------- lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "--- 进行处理 数据!---"}) lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: fmt.Sprintf("开始时间:%s 结束时间:%s", 开始时间, 结束时间)}) // 先整体向上偏移 for _, i2 := range 部点终端_list { T_min := Task.Read_TaskData_min(T_task_id, i2.T_sn, i2.T_id, "", "") if T_min < RoundToDecimal(温度控制范围最小值+0.1, 1) { Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, i2.T_sn, i2.T_id, "", "", RoundToDecimal(温度控制范围最小值+0.1-T_min, 1), 0) } } // ----------获取保留数据------------ var 开空开, 开空开驼峰结束时间, 保空开, 保空开驼峰结束时间 string var valueStrings1, valueStrings2, BWXValueStrings []string if Task_r.T_device_type != "X" { valueStrings1, valueStrings2, 开空开, 开空开驼峰结束时间, 保空开, 保空开驼峰结束时间 = c.GetRetainData(Task_r, 部点终端_sn_list) } else { BWXValueStrings = c.GetBWXRetainData(Task_r, 部点终端_sn_list, 结束时间, 趋势时间) } // ----------获取保留数据结束------------ var AVGClassList_r []AVGClassList for _, i2 := range 部点终端_list { T_max := Task.Read_TaskData_max(T_task_id, i2.T_sn, i2.T_id, 开始时间, 结束时间) T_min := Task.Read_TaskData_min(T_task_id, i2.T_sn, i2.T_id, "", "") 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}) } for _, AVGClassList_i := range AVGClassList_r { if AVGClassList_i.T_max < 温度控制范围最高值 && AVGClassList_i.T_min > 温度控制范围最小值 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "测点 " + lib.To_string(AVGClassList_i.T_id) + " 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃ " + " 最小值:" + lib.To_string(AVGClassList_i.T_min) + "℃ " + " 符合要求!"}) continue } var vgaca float64 if RoundToDecimal(AVGClassList_i.T_max-AVGClassList_i.T_min, 1) > RoundToDecimal(温度控制范围最高值-温度控制范围最小值-0.4, 1) { // 压缩 diff := RoundToDecimal(AVGClassList_i.T_max-AVGClassList_i.T_min, 1) // 获取压缩度 compress := RoundToDecimal((温度控制范围最高值-温度控制范围最小值-0.6)/diff, 2) // 压缩 Task.UpdateTaskDataTemperatureAndHumidityByGeometric(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", compress, 1) T_max_compress := RoundToDecimal(AVGClassList_i.T_max*compress, 1) T_min_compress := RoundToDecimal(AVGClassList_i.T_min*compress, 1) // 判断压缩后是否在 温度控制范围最小值-温度控制范围最高值范围内 不做处理 if T_max_compress <= RoundToDecimal(温度控制范围最高值-0.1, 1) && T_min_compress >= RoundToDecimal(温度控制范围最小值+0.1, 1) { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + lib.To_string(AVGClassList_i.T_id) + " 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃ " + " 最小值:" + lib.To_string(AVGClassList_i.T_min) + "℃ " + " 压缩:" + lib.To_string(compress) + " 压缩后最大值:" + lib.To_string(T_max_compress) + "℃ " + " 压缩后最小值:" + lib.To_string(T_min_compress) + "℃ "}) continue } // 压缩后仍高于 温度控制范围最高值,向下偏移 if T_max_compress >= 温度控制范围最高值 { vgaca = RoundToDecimal(T_max_compress-温度控制范围最高值+0.1, 1) lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + lib.To_string(AVGClassList_i.T_id) + " 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃ " + " 最小值:" + lib.To_string(AVGClassList_i.T_min) + "℃ " + " 压缩:" + lib.To_string(compress) + " 压缩后最大值:" + lib.To_string(RoundToDecimal(AVGClassList_i.T_max*compress, 1)) + "℃ " + " 压缩后最小值:" + lib.To_string(RoundToDecimal(AVGClassList_i.T_min*compress, 1)) + "℃ " + " 数据偏差:" + lib.To_string(vgaca) + "℃ " + " 向下偏移:" + lib.To_string(vgaca) + "℃ "}) Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", -vgaca, 0) continue } // 压缩后仍低于 温度控制范围最小值,向上偏移 if T_min_compress <= 温度控制范围最小值 { // 向上偏移 vgaca = RoundToDecimal(温度控制范围最小值-AVGClassList_i.T_min*compress+0.1, 1) lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + lib.To_string(AVGClassList_i.T_id) + " 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃ " + " 最小值:" + lib.To_string(AVGClassList_i.T_min) + "℃ " + " 压缩:" + lib.To_string(compress) + " 压缩后最大值:" + lib.To_string(RoundToDecimal(AVGClassList_i.T_max*compress, 1)) + "℃ " + " 压缩后最小值:" + lib.To_string(RoundToDecimal(AVGClassList_i.T_min*compress, 1)) + "℃ " + " 数据偏差:" + lib.To_string(vgaca) + "℃ " + " 向上偏移:" + lib.To_string(vgaca) + "℃ "}) Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", vgaca, 0) } continue } else { // 向下偏移 if AVGClassList_i.T_max >= 温度控制范围最高值 { vgaca = RoundToDecimal(AVGClassList_i.T_max-温度控制范围最高值+0.1, 1) lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + lib.To_string(AVGClassList_i.T_id) + " 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃ " + " 最小值:" + lib.To_string(AVGClassList_i.T_min) + "℃ " + " 数据偏差:" + lib.To_string(vgaca) + "℃ " + " 向下偏移:" + lib.To_string(vgaca) + "℃ "}) // 偏移 Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", -vgaca, 0) continue } if AVGClassList_i.T_min <= 温度控制范围最小值 { vgaca = RoundToDecimal(温度控制范围最小值-AVGClassList_i.T_min+0.1, 1) lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + lib.To_string(AVGClassList_i.T_id) + " 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃ " + " 最小值:" + lib.To_string(AVGClassList_i.T_min) + "℃ " + " 数据偏差: " + lib.To_string(vgaca) + "℃ " + " 向上偏移:" + lib.To_string(vgaca) + "℃ "}) Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", vgaca, 0) } } } // ----------恢复保留数据------------ if Task_r.T_device_type != "X" { c.SaveRetainData(Task_r, 部点终端_list, valueStrings1, valueStrings2, 开空开, 开空开驼峰结束时间, 保空开, 保空开驼峰结束时间) } else { c.SaveBWXRetainData(Task_r, 部点终端_list, BWXValueStrings, 结束时间, 趋势时间, 60) } // ----------恢复保留数据结束------------ lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "完成!"}) // Close the connection c.Ctx.ResponseWriter.WriteHeader(http.StatusOK) } // 绑定点与终端比对 (绑定点数据自检) 终端数据为参照物,绑定点数据在终端偏差±1℃,保温箱为±0.5℃ func (c *TaskDataHandleController) SSE_Comparison_between_binding_points_and_terminals() { T_task_id := c.GetString("T_task_id") // v26nplogbwt1 T_deviation, _ := c.GetFloat("T_deviation", 1.0) // 误差绑定点数据与终端对比偏差 c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream") c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache") c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive") lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "任务开始......"}) Task_r, err := Task.Read_Task(T_task_id) if err != nil { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取任务信息失败!"}) return } // 保温箱偏差为0.5 if Task_r.T_device_type == "X" { T_deviation = 0.5 } // -------------------- 获取开始时间-------------------- 温度控制范围最高值 := float64(lib.To_float32(VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "温度控制范围最高值"))) if 温度控制范围最高值 == 0 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温度控制范围最高值 标签值不正确!"}) return } 温度控制范围最小值 := float64(lib.To_float32(VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "温度控制范围最小值"))) if 温度控制范围最小值 == 0 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温度控制范围最小值 标签值不正确!"}) return } // 均匀性布点 产品存放区域测点 部点终端_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "均匀性布点|产品存放区域测点") if len(部点终端_list) <= 2 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "均匀性布点,产品存放区域测点 太少了,至少两条以上!"}) return } 部点终端_sn_list := Device.JoinDeviceClassListSnToString(部点终端_list) var 开始时间, 结束时间, 趋势时间 string 开始时间, 结束时间, 趋势时间 = c.GetStartTimeAndEndTime(Task_r, 部点终端_sn_list, 温度控制范围最高值) if 开始时间 == "" || 结束时间 == "" { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 开始时间 或 结束时间 结束时间!"}) return } // ----------获取保留数据------------ var 开空开, 开空开驼峰结束时间, 保空开, 保空开驼峰结束时间 string var valueStrings1, valueStrings2, BWXValueStrings []string if Task_r.T_device_type != "X" { valueStrings1, valueStrings2, 开空开, 开空开驼峰结束时间, 保空开, 保空开驼峰结束时间 = c.GetRetainData(Task_r, 部点终端_sn_list) } else { BWXValueStrings = c.GetBWXRetainData(Task_r, 部点终端_sn_list, 结束时间, 趋势时间) } // ----------获取保留数据结束------------ 监测终端_list := Device.Read_DeviceClassList_List_id_By_Terminal(Task_r.T_class, true) if len(监测终端_list) < 1 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 监测终端!"}) return } 温湿度绑定点_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "温湿度绑定点") if len(温湿度绑定点_list) < 1 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 温湿度绑定点!"}) return } if len(监测终端_list) != len(温湿度绑定点_list) { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "监测终端 和 温湿度绑定点 数量不一致!"}) return } var 监测终端01, 监测终端02, 温湿度绑定点1, 温湿度绑定点2 Device.DeviceClassList for _, list := range 监测终端_list { if strings.Contains(list.T_remark, "监测终端01") { 监测终端01 = list } if strings.Contains(list.T_remark, "监测终端02") { 监测终端02 = list } } for _, list := range 温湿度绑定点_list { if strings.Contains(list.T_remark, "温湿度绑定点1") { 温湿度绑定点1 = list } if strings.Contains(list.T_remark, "温湿度绑定点2") { 温湿度绑定点2 = list } } var 温湿度绑定点vga, 监测终端vga float64 温湿度绑定点vga = Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点1.T_sn, 温湿度绑定点1.T_id, 开始时间, 结束时间) if 温湿度绑定点vga == 0 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温湿度绑定点1 无数据!请先处理数据!"}) return } 监测终端vga = Task.Read_TaskData_AVG(T_task_id, 监测终端01.T_sn, 监测终端01.T_id, 开始时间, 结束时间) if 监测终端vga == 0 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "监测终端01 无数据!请先处理数据!"}) return } 温湿度绑定点vga = RoundToDecimal(温湿度绑定点vga, 1) 监测终端vga = RoundToDecimal(监测终端vga, 1) if len(监测终端_list) == 1 { // 只有一个终端,直接偏移到±T_deviation 区间内 if (温湿度绑定点vga > 监测终端vga && 温湿度绑定点vga < 监测终端vga+T_deviation) || (温湿度绑定点vga < 监测终端vga && 温湿度绑定点vga > 监测终端vga-T_deviation) { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "" + "温湿度绑定点1平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " + "监测终端01 平均值" + lib.To_string(监测终端vga) + "℃ " + "数据偏差: " + lib.To_string(RoundToDecimal(监测终端vga-温湿度绑定点vga, 1)) + "℃ " + "设置:" + lib.To_string(T_deviation) + "℃" + "符合要求!"}) } T_max := Task.Read_TaskData_max(T_task_id, 温湿度绑定点1.T_sn, 温湿度绑定点1.T_id, 开始时间, 结束时间) T_min := Task.Read_TaskData_min(T_task_id, 温湿度绑定点1.T_sn, 温湿度绑定点1.T_id, 开始时间, 结束时间) // 平均值向下偏移 if 温湿度绑定点vga > RoundToDecimal(监测终端vga+T_deviation, 1) { c.SetAverageShiftedDownward(T_task_id, 温湿度绑定点1.T_id, T_deviation, 监测终端vga, 温湿度绑定点vga, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "") } // 平均值向上偏移 if 温湿度绑定点vga < RoundToDecimal(监测终端vga-T_deviation, 1) { c.SetAverageShiftedUpward(T_task_id, 温湿度绑定点1.T_id, T_deviation, 监测终端vga, 温湿度绑定点vga, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "") } } else if len(监测终端_list) == 2 { // 有两个终端,找出目标温湿度绑定点vga, 目标温湿度绑定点2vga最优解后偏移 var 温湿度绑定点2vga, 监测终端2vga float64 温湿度绑定点2vga = Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点2.T_sn, 温湿度绑定点2.T_id, 开始时间, 结束时间) if 温湿度绑定点2vga == 0 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温湿度绑定点3 无数据!请先处理数据!"}) } 监测终端2vga = Task.Read_TaskData_AVG(T_task_id, 监测终端02.T_sn, 监测终端02.T_id, 开始时间, 结束时间) if 监测终端2vga == 0 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "监测终端02 无数据!请先处理数据!"}) } 温湿度绑定点2vga = RoundToDecimal(温湿度绑定点2vga, 1) 监测终端2vga = RoundToDecimal(监测终端2vga, 1) if math.Abs(监测终端2vga-监测终端vga) > 3 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "监测终端vga|监测终端2vga 绝对值相差超过3度,无法处理!"}) return } // 获取监测终端和绑定点的平均值 目标温湿度绑定点vga, 目标温湿度绑定点2vga, isExist := findBindingPointsOptimalAdjustment(监测终端vga, 监测终端2vga, 温湿度绑定点vga, 温湿度绑定点2vga, T_deviation) if !isExist { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 最优 温湿度绑定点1|温湿度绑定点2| 调整值!"}) return } lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "监测终端01 平均值" + lib.To_string(监测终端vga) + "℃ " + "监测终端02 平均值" + lib.To_string(监测终端2vga) + "℃ " + "温湿度绑定点1 原始平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " + "温湿度绑定点2 原始平均值:" + lib.To_string(温湿度绑定点2vga) + "℃ " + "温湿度绑定点1 最优平均值:" + lib.To_string(目标温湿度绑定点vga) + "℃ " + "温湿度绑定点2 最优平均值:" + lib.To_string(目标温湿度绑定点2vga) + "℃ " + "设置:" + lib.To_string(T_deviation) + "℃"}) if 目标温湿度绑定点vga != 温湿度绑定点vga { T_max := Task.Read_TaskData_max(T_task_id, 温湿度绑定点1.T_sn, 温湿度绑定点1.T_id, 开始时间, 结束时间) T_min := Task.Read_TaskData_min(T_task_id, 温湿度绑定点1.T_sn, 温湿度绑定点1.T_id, 开始时间, 结束时间) // 平均值向下偏移 if 温湿度绑定点vga > RoundToDecimal(目标温湿度绑定点vga, 1) { c.SetAverageShiftedDownward(T_task_id, 温湿度绑定点1.T_id, 0, 目标温湿度绑定点vga, 温湿度绑定点vga, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "") } // 平均值向上偏移 if 温湿度绑定点vga < RoundToDecimal(目标温湿度绑定点vga, 1) { c.SetAverageShiftedUpward(T_task_id, 温湿度绑定点1.T_id, 0, 目标温湿度绑定点vga, 温湿度绑定点vga, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "") } } if 目标温湿度绑定点2vga != 温湿度绑定点2vga { T_max := Task.Read_TaskData_max(T_task_id, 温湿度绑定点2.T_sn, 温湿度绑定点2.T_id, 开始时间, 结束时间) T_min := Task.Read_TaskData_min(T_task_id, 温湿度绑定点2.T_sn, 温湿度绑定点2.T_id, 开始时间, 结束时间) // 平均值向下偏移 if 温湿度绑定点vga > RoundToDecimal(目标温湿度绑定点vga, 1) { c.SetAverageShiftedDownward(T_task_id, 温湿度绑定点2.T_id, 0, 目标温湿度绑定点vga, 温湿度绑定点vga, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "") } // 平均值向上偏移 if 温湿度绑定点vga < RoundToDecimal(目标温湿度绑定点vga, 1) { c.SetAverageShiftedUpward(T_task_id, 温湿度绑定点2.T_id, 0, 目标温湿度绑定点vga, 温湿度绑定点vga, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "") } } } // ----------恢复保留数据------------ if Task_r.T_device_type != "X" { c.SaveRetainData(Task_r, 部点终端_list, valueStrings1, valueStrings2, 开空开, 开空开驼峰结束时间, 保空开, 保空开驼峰结束时间) } else { c.SaveBWXRetainData(Task_r, 部点终端_list, BWXValueStrings, 结束时间, 趋势时间, 60) } // ----------恢复保留数据结束------------ lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "完成!"}) // Close the connection c.Ctx.ResponseWriter.WriteHeader(http.StatusOK) } /* 绑定点与冷热点比对 (冷热点数据自检)绑定点数据为参照物,绑定点数据在终端偏差±1℃,保温箱为±0.5℃ 固定偏移一固定值,降到超限的平均复制,仍然超限再压缩 */ func (c *TaskDataHandleController) SSE_Compare_binding_points_with_cold_and_hot_spots() { T_task_id := c.GetString("T_task_id") // v26nplogbwt1 T_deviation, _ := c.GetFloat("T_deviation", 1.0) // 偏差时间 c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream") c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache") c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive") lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "任务开始......"}) Task_r, err := Task.Read_Task(T_task_id) if err != nil { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取任务信息失败!"}) return } // 保温箱偏差为0.5 if Task_r.T_device_type == "X" { T_deviation = 0.5 } 温度控制范围最高值 := float64(lib.To_float32(VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "温度控制范围最高值"))) if 温度控制范围最高值 == 0 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温度控制范围最高值 标签值不正确!"}) return } 温度控制范围最小值 := float64(lib.To_float32(VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "温度控制范围最小值"))) if 温度控制范围最小值 == 0 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温度控制范围最小值 标签值不正确!"}) return } // ------- 温湿度绑定点 温湿度绑定点1_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "温湿度绑定点1") if len(温湿度绑定点1_list) != 1 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温湿度绑定点1 中找到 " + lib.To_string(len(温湿度绑定点1_list)) + "条,布点终端异常!"}) return } 温湿度绑定点2_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "温湿度绑定点2") if len(温湿度绑定点2_list) != 1 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "温湿度绑定点2 没找到,将 温湿度绑定点1 设置低点"}) 温湿度绑定点2_list = 温湿度绑定点1_list } // 均匀性布点 产品存放区域测点 部点终端_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "均匀性布点|产品存放区域测点") if len(部点终端_list) == 0 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "没有找到 均匀性布点,产品存放区域测点,作业出入口总测点 测点数据!"}) return } 部点终端_sn_list := Device.JoinDeviceClassListSnToString(部点终端_list) var 开始时间, 结束时间, 趋势时间 string 开始时间, 结束时间, 趋势时间 = c.GetStartTimeAndEndTime(Task_r, 部点终端_sn_list, 温度控制范围最高值) if 开始时间 == "" || 结束时间 == "" { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 开始时间 或 结束时间 结束时间!"}) return } // ----------获取保留数据------------ var 开空开, 开空开驼峰结束时间, 保空开, 保空开驼峰结束时间 string var valueStrings1, valueStrings2, BWXValueStrings []string if Task_r.T_device_type != "X" { valueStrings1, valueStrings2, 开空开, 开空开驼峰结束时间, 保空开, 保空开驼峰结束时间 = c.GetRetainData(Task_r, 部点终端_sn_list) } else { BWXValueStrings = c.GetBWXRetainData(Task_r, 部点终端_sn_list, 结束时间, 趋势时间) } // ----------获取保留数据结束------------ lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "--- 开始时间--- " + 开始时间}) lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "--- 结束时间--- " + 结束时间}) type AVGClassList struct { T_id string T_vga float64 T_max float64 T_min float64 } 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), 开始时间, 结束时间) if len(TaskData_Total_GroupBySnId) == 0 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温湿度绑定点 无数据"}) return } for _, v := range TaskData_Total_GroupBySnId { if v.Total == 0 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温湿度绑定点[" + v.T_id + "] 无数据"}) return } } 温湿度绑定点1vga := Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点1_list[0].T_sn, 温湿度绑定点1_list[0].T_id, 开始时间, 结束时间) 温湿度绑定点2vga := Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点2_list[0].T_sn, 温湿度绑定点2_list[0].T_id, 开始时间, 结束时间) if 温湿度绑定点1vga == 温湿度绑定点2vga { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "温湿度绑定点1 与 温湿度绑定点2 平均值相等,将 进行上下偏移处理!"}) 温湿度绑定点1vga += T_deviation / 2 温湿度绑定点2vga -= T_deviation / 2 T_deviation /= 2 } var 温湿度绑定点vga_H, 温湿度绑定点vga_L AVGClassList if 温湿度绑定点1vga > 温湿度绑定点2vga { 温湿度绑定点vga_H.T_id = 温湿度绑定点1_list[0].T_id 温湿度绑定点vga_H.T_vga = RoundToDecimal(温湿度绑定点1vga, 1) 温湿度绑定点vga_L.T_id = 温湿度绑定点2_list[0].T_id 温湿度绑定点vga_L.T_vga = RoundToDecimal(温湿度绑定点2vga, 1) } else { 温湿度绑定点vga_L.T_id = 温湿度绑定点1_list[0].T_id 温湿度绑定点vga_L.T_vga = RoundToDecimal(温湿度绑定点1vga, 1) 温湿度绑定点vga_H.T_id = 温湿度绑定点2_list[0].T_id 温湿度绑定点vga_H.T_vga = RoundToDecimal(温湿度绑定点2vga, 1) } fmt.Println("温湿度绑定点:", 温湿度绑定点vga_H, 温湿度绑定点vga_L) var Average_H_List []Task.TaskData_Average // 热点 var Average_L_List []Task.TaskData_Average // 冷点 snList := Device.JoinDeviceClassListSnToString(部点终端_list) TaskData_Average_GroupBySnId := Task.Read_TaskData_Average_GroupBySnId(Task_r.T_task_id, snList, 开始时间, 结束时间) if len(TaskData_Average_GroupBySnId) < 2 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "未找到 均匀性布点,产品存放区域测点 数据冷热点,平均值数据少于2条!"}) return } for _, average := range TaskData_Average_GroupBySnId { if RoundToDecimal(average.Average, 1) > RoundToDecimal(温湿度绑定点vga_H.T_vga+T_deviation, 1) { average.Average = RoundToDecimal(average.Average, 1) Average_H_List = append(Average_H_List, average) } if RoundToDecimal(average.Average, 1) < RoundToDecimal(温湿度绑定点vga_L.T_vga-T_deviation, 1) { average.Average = RoundToDecimal(average.Average, 1) Average_L_List = append(Average_L_List, average) } } lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "------ 进行 高点处理 ------"}) lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "------ 高点平均值 " + lib.To_string(温湿度绑定点vga_H.T_vga) + "------"}) if len(Average_H_List) == 0 { Average_H := TaskData_Average_GroupBySnId[0] // 高点不在冷热点范围 if RoundToDecimal(Average_H.Average, 1) < RoundToDecimal(温湿度绑定点vga_H.T_vga-T_deviation, 1) && RoundToDecimal(Average_H.Average, 1) > RoundToDecimal(温湿度绑定点vga_L.T_vga+T_deviation, 1) { // 热点向上偏移到高点-T_deviation T_max := Task.Read_TaskData_max(T_task_id, Average_H.T_sn, Average_H.T_id, 开始时间, 结束时间) T_min := Task.Read_TaskData_min(T_task_id, Average_H.T_sn, Average_H.T_id, 开始时间, 结束时间) c.SetAverageShiftedUpward(T_task_id, Average_H.T_id, T_deviation, 温湿度绑定点vga_H.T_vga, Average_H.Average, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "") } } else { for _, Average_H := range Average_H_List { // 热点向下偏移到高点范围 T_max := Task.Read_TaskData_max(T_task_id, Average_H.T_sn, Average_H.T_id, 开始时间, 结束时间) T_min := Task.Read_TaskData_min(T_task_id, Average_H.T_sn, Average_H.T_id, 开始时间, 结束时间) c.SetAverageShiftedDownward(T_task_id, Average_H.T_id, T_deviation, 温湿度绑定点vga_H.T_vga, Average_H.Average, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "") } } lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "------ 进行 低点处理 ------"}) lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "------ 低点平均值 " + lib.To_string(温湿度绑定点vga_L.T_vga) + "------"}) if len(Average_L_List) == 0 { Average_L := TaskData_Average_GroupBySnId[0] // 冷点不在冷热点范围 if RoundToDecimal(Average_L.Average, 1) < RoundToDecimal(温湿度绑定点vga_L.T_vga+T_deviation, 1) && RoundToDecimal(Average_L.Average, 1) < RoundToDecimal(温湿度绑定点vga_L.T_vga-T_deviation, 1) { // 热点向下偏移到高点范围 T_max := Task.Read_TaskData_max(T_task_id, Average_L.T_sn, Average_L.T_id, 开始时间, 结束时间) T_min := Task.Read_TaskData_min(T_task_id, Average_L.T_sn, Average_L.T_id, 开始时间, 结束时间) c.SetAverageShiftedDownward(T_task_id, Average_L.T_id, T_deviation, 温湿度绑定点vga_H.T_vga, Average_L.Average, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "") } } else { for _, Average_L := range Average_L_List { // 热点向下偏移到高点范围 T_max := Task.Read_TaskData_max(T_task_id, Average_L.T_sn, Average_L.T_id, 开始时间, 结束时间) T_min := Task.Read_TaskData_min(T_task_id, Average_L.T_sn, Average_L.T_id, 开始时间, 结束时间) c.SetAverageShiftedUpward(T_task_id, Average_L.T_id, T_deviation, 温湿度绑定点vga_L.T_vga, Average_L.Average, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "") } } // ----------恢复保留数据------------ if Task_r.T_device_type != "X" { c.SaveRetainData(Task_r, 部点终端_list, valueStrings1, valueStrings2, 开空开, 开空开驼峰结束时间, 保空开, 保空开驼峰结束时间) } else { c.SaveBWXRetainData(Task_r, 部点终端_list, BWXValueStrings, 结束时间, 趋势时间, 60) } // ----------恢复保留数据结束------------ lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "完成!"}) // Close the connection c.Ctx.ResponseWriter.WriteHeader(http.StatusOK) } // 获取相邻2个终端值平均复制到 func (c *TaskDataHandleController) SetAdjacentDeviceAVGTaskData(T_task_id string, device Device.DeviceClassList, StartTime, EndTime string) { DeviceClassListT_remark_r := Device.Read_DeviceClassList_List_id_T_remark(device.T_class, device.T_remark) // 分组统计每个sn的数据数量 snList := Device.JoinDeviceClassListSnToString(DeviceClassListT_remark_r) TaskData_Total_GroupBySnId := Task.Read_TaskData_Total_GroupBySnId(T_task_id, snList, StartTime, EndTime) if len(TaskData_Total_GroupBySnId) < 2 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "[" + device.T_remark + "]中没有找到 至少2条 可用数据"}) return } // 获取 备注 下面关联设备,数量 DeviceClassListT_remark_r_list_MAX := TaskData_Total_GroupBySnId[0].Total TaskData_Total_GroupBySnId_Map := make(map[string]int64) for _, v := range TaskData_Total_GroupBySnId { TaskData_Total_GroupBySnId_Map[v.T_sn] = v.Total } var completeDataDeviceClassList []Device.DeviceClassList for _, v := range DeviceClassListT_remark_r { if TaskData_Total_GroupBySnId_Map[v.T_sn] == DeviceClassListT_remark_r_list_MAX || v.T_sn == device.T_sn { completeDataDeviceClassList = append(completeDataDeviceClassList, v) } } if len(completeDataDeviceClassList) < 3 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "[" + device.T_remark + "]中没有找到 至少2条 完整可用数据"}) return } twoDevice := getBeforeAndAfter(device.T_id, completeDataDeviceClassList) sn1, id_str1 := twoDevice[0].T_sn, twoDevice[0].T_id sn2, id_str2 := twoDevice[1].T_sn, twoDevice[1].T_id lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: device.T_sn + "," + device.T_id + "开始平均复制到" + fmt.Sprintf("%s,%s|%s,%s", sn1, id_str1, sn2, id_str2)}) List1, _ := Task.Read_TaskData_ById_List_AES(T_task_id, sn1, id_str1, StartTime, EndTime, 0, 9999) List2, _ := Task.Read_TaskData_ById_List_AES(T_task_id, sn2, id_str2, StartTime, EndTime, 0, 9999) num := len(List1) if len(List2) < len(List1) { num = len(List2) } if num == 0 { return } T_saveT := 60 //var list []Task.TaskData_ ct, _ := lib.TimeStrToTime(List1[0].T_time) var valueStrings []string for i := 0; i < num; i++ { if List1[i].T_time != List2[i].T_time { 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)}) return } T_t := (List1[i].T_t + List2[i].T_t) / 2 T_rh := (List1[i].T_rh + List2[i].T_rh) / 2 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"))) ct = ct.Add(time.Second * time.Duration(T_saveT)) } Task.DeleteTaskDataByTimeRange(T_task_id, device.T_sn, device.T_id, StartTime, EndTime) err := Task.Batch_Adds_TaskData(T_task_id, valueStrings) if err == nil { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: fmt.Sprintf("%d/%d", len(valueStrings), len(valueStrings))}) } } func getBeforeAndAfter(T_id string, data []Device.DeviceClassList) []Device.DeviceClassList { var result []Device.DeviceClassList var index int for i, d := range data { if d.T_id == T_id { index = i break } } if index == 0 { result = append(result, data[len(data)-1], data[1]) } else if index == len(data)-1 { result = append(result, data[len(data)-2], data[0]) } else { result = append(result, data[index-1], data[index+1]) } return result } func RoundToDecimal(num float64, decimal int) float64 { shift := math.Pow(10, float64(decimal)) return math.Round(num*shift) / shift } /* 数据自检名称:平均值数据自检 测点:柜内所有测点|箱内所有测点|均匀性布点和产品存放区域测点、温湿度绑定点01、温湿度绑定点02 时间:采用“绑定点数据自检”的时间 策略:先执行完成“绑定点数据自检”后,温湿度绑定点01和温湿度绑定点02的数据就作为基准数据不变,温湿度绑定点01平均值与柜内所有测点平均值之间的差异在±0.5℃范围以内,温湿度绑定点02平均值与柜内所有测点平均值之间的差异在±0.5℃范围以内,若柜内所有测点的平均值较大或较小,则对柜内所有测点中平均值较大或较小的测点曲线进行偏移调整,使柜内所有测点的平均值靠近温湿度绑定点的平均值,从而达到绑定点与柜内所有测点的平均值差异在±0.5℃。以上“柜内所有测点”要分别换成“箱内所有测点”、“均匀性布点和产品存放区域测点”;“平均值数据自检”和“冷热点数据自检”可以同时勾选(冷库和冷车会用到)进行自检也可以单独执行(冷柜和保温箱只执行“平均值数据自检”) */ func (c *TaskDataHandleController) SSE_Compare_binding_points_with_Average() { T_task_id := c.GetString("T_task_id") // v26nplogbwt1 T_deviation := 0.5 // 偏差时间 c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream") c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache") c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive") lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "任务开始......"}) Task_r, err := Task.Read_Task(T_task_id) if err != nil { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取任务信息失败!"}) return } // 保温箱偏差为0.5 if Task_r.T_device_type == "X" { T_deviation = 0.5 } 温度控制范围最高值 := float64(lib.To_float32(VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "温度控制范围最高值"))) if 温度控制范围最高值 == 0 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温度控制范围最高值 标签值不正确!"}) return } 温度控制范围最小值 := float64(lib.To_float32(VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "温度控制范围最小值"))) if 温度控制范围最小值 == 0 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温度控制范围最小值 标签值不正确!"}) return } // 均匀性布点 产品存放区域测点 部点终端_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "均匀性布点|柜内所有测点|箱内所有测点|产品存放区域测点") 部点终端_sn_list := Device.JoinDeviceClassListSnToString(部点终端_list) var 开始时间, 结束时间, 趋势时间 string 开始时间, 结束时间, 趋势时间 = c.GetStartTimeAndEndTime(Task_r, 部点终端_sn_list, 温度控制范围最高值) if 开始时间 == "" || 结束时间 == "" { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 开始时间 或 结束时间 结束时间!"}) return } // ----------获取保留数据------------ var 开空开, 开空开驼峰结束时间, 保空开, 保空开驼峰结束时间 string var valueStrings1, valueStrings2, BWXValueStrings []string if Task_r.T_device_type != "X" { valueStrings1, valueStrings2, 开空开, 开空开驼峰结束时间, 保空开, 保空开驼峰结束时间 = c.GetRetainData(Task_r, 部点终端_sn_list) } else { BWXValueStrings = c.GetBWXRetainData(Task_r, 部点终端_sn_list, 结束时间, 趋势时间) } // ----------获取保留数据结束------------ lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "--- 开始时间--- " + 开始时间}) lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "--- 结束时间--- " + 结束时间}) if len(部点终端_list) == 0 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "没有找到 柜内所有测点|箱内所有测点|均匀性布点|产品存放区域测点 测点数据!"}) return } snList := Device.JoinDeviceClassListSnToString(部点终端_list) originalAvg := Task.Read_TaskData_Average(Task_r.T_task_id, snList, 开始时间, 结束时间) originalAvg = RoundToDecimal(originalAvg, 1) 温湿度绑定点_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "温湿度绑定点") if len(温湿度绑定点_list) < 1 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 温湿度绑定点!"}) return } var 温湿度绑定点1, 温湿度绑定点2 Device.DeviceClassList for _, list := range 温湿度绑定点_list { if strings.Contains(list.T_remark, "温湿度绑定点1") { 温湿度绑定点1 = list } if strings.Contains(list.T_remark, "温湿度绑定点2") { 温湿度绑定点2 = list } } 温湿度绑定点vga := Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点1.T_sn, 温湿度绑定点1.T_id, 开始时间, 结束时间) if 温湿度绑定点vga == 0 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温湿度绑定点1 无数据!请先处理数据!"}) return } if len(温湿度绑定点_list) == 1 { 温湿度绑定点vga = RoundToDecimal(温湿度绑定点vga, 1) lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "------ 进行 柜内所有测点|箱内所有测点|均匀性布点|产品存放区域测点 平均值处理 ------"}) if (originalAvg >= 温湿度绑定点vga && originalAvg <= 温湿度绑定点vga+T_deviation) || (originalAvg <= 温湿度绑定点vga && originalAvg >= 温湿度绑定点vga-T_deviation) { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "" + "温湿度绑定点1 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " + "测点 平均值" + lib.To_string(originalAvg) + "℃ " + "数据偏差: " + lib.To_string(RoundToDecimal(math.Abs(originalAvg-温湿度绑定点vga), 1)) + "℃ " + "设置:" + lib.To_string(T_deviation) + "℃" + "符合要求!"}) } else { // 平均值最低点向上偏移 if originalAvg < 温湿度绑定点vga-T_deviation { for originalAvg < 温湿度绑定点vga-T_deviation { TaskData_Average_GroupBySnId := Task.Read_TaskData_Average_GroupBySnId(Task_r.T_task_id, snList, 开始时间, 结束时间) if len(TaskData_Average_GroupBySnId) == 0 { break } Average_L := TaskData_Average_GroupBySnId[len(TaskData_Average_GroupBySnId)-1] T_max := Task.Read_TaskData_max(T_task_id, Average_L.T_sn, Average_L.T_id, 开始时间, 结束时间) T_min := Task.Read_TaskData_min(T_task_id, Average_L.T_sn, Average_L.T_id, 开始时间, 结束时间) c.SetAverageShiftedUpward(T_task_id, Average_L.T_id, T_deviation, RoundToDecimal(Average_L.Average+0.1, 1), Average_L.Average, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "") lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "" + "温湿度绑定点1 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " + "测点 平均值" + lib.To_string(originalAvg) + "℃ " + "数据偏差: " + lib.To_string(math.Abs(originalAvg-温湿度绑定点vga)) + "℃ " + "设置:" + lib.To_string(T_deviation) + "℃" + "向上偏移0.1℃"}) originalAvg = Task.Read_TaskData_Average(Task_r.T_task_id, snList, 开始时间, 结束时间) originalAvg = RoundToDecimal(originalAvg, 1) } lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "" + "温湿度绑定点1 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " + "测点 平均值" + lib.To_string(originalAvg) + "℃ " + "数据偏差: " + lib.To_string(RoundToDecimal(math.Abs(originalAvg-温湿度绑定点vga), 1)) + "℃ " + "设置:" + lib.To_string(T_deviation) + "℃" + "符合要求!"}) } // 向下偏移 if originalAvg > 温湿度绑定点vga+T_deviation { for originalAvg > 温湿度绑定点vga+T_deviation { // 热点向下偏移到高点范围 TaskData_Average_GroupBySnId := Task.Read_TaskData_Average_GroupBySnId(Task_r.T_task_id, snList, 开始时间, 结束时间) if len(TaskData_Average_GroupBySnId) == 0 { break } Average_H := TaskData_Average_GroupBySnId[0] T_max := Task.Read_TaskData_max(T_task_id, Average_H.T_sn, Average_H.T_id, 开始时间, 结束时间) T_min := Task.Read_TaskData_min(T_task_id, Average_H.T_sn, Average_H.T_id, 开始时间, 结束时间) c.SetAverageShiftedDownward(T_task_id, Average_H.T_id, T_deviation, RoundToDecimal(Average_H.Average-0.1, 1), Average_H.Average, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "") lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "" + "温湿度绑定点1 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " + "测点 平均值" + lib.To_string(originalAvg) + "℃ " + "数据偏差: " + lib.To_string(RoundToDecimal(math.Abs(originalAvg-温湿度绑定点vga), 1)) + "℃ " + "设置:" + lib.To_string(T_deviation) + "℃" + "向下偏移0.1℃"}) originalAvg = Task.Read_TaskData_Average(Task_r.T_task_id, snList, 开始时间, 结束时间) originalAvg = RoundToDecimal(originalAvg, 1) } lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "" + "温湿度绑定点1 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " + "测点 平均值" + lib.To_string(originalAvg) + "℃ " + "数据偏差: " + lib.To_string(RoundToDecimal(math.Abs(originalAvg-温湿度绑定点vga), 1)) + "℃ " + "设置:" + lib.To_string(T_deviation) + "℃" + "符合要求!"}) } } } else if len(温湿度绑定点_list) == 2 { 温湿度绑定点2vga := Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点2.T_sn, 温湿度绑定点2.T_id, 开始时间, 结束时间) if 温湿度绑定点2vga == 0 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温湿度绑定点2 无数据!请先处理数据!"}) return } // 获取最优平均值 目标originalAvg := findAverageOptimalAdjustment(温湿度绑定点vga, 温湿度绑定点2vga, originalAvg) 目标originalAvg = RoundToDecimal(目标originalAvg, 1) if 目标originalAvg != originalAvg { // 平均值最低点向上偏移 if originalAvg < 目标originalAvg { for originalAvg < 目标originalAvg { TaskData_Average_GroupBySnId := Task.Read_TaskData_Average_GroupBySnId(Task_r.T_task_id, snList, 开始时间, 结束时间) if len(TaskData_Average_GroupBySnId) == 0 { break } Average_L := TaskData_Average_GroupBySnId[len(TaskData_Average_GroupBySnId)-1] T_max := Task.Read_TaskData_max(T_task_id, Average_L.T_sn, Average_L.T_id, 开始时间, 结束时间) T_min := Task.Read_TaskData_min(T_task_id, Average_L.T_sn, Average_L.T_id, 开始时间, 结束时间) c.SetAverageShiftedUpward(T_task_id, Average_L.T_id, T_deviation, RoundToDecimal(Average_L.Average+0.1, 1), Average_L.Average, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "") lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "" + " 温湿度绑定点1 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " + " 温湿度绑定点2 平均值:" + lib.To_string(温湿度绑定点2vga) + "℃ " + " 测点 平均值" + lib.To_string(originalAvg) + "℃ " + " 测点 最优平均值" + lib.To_string(目标originalAvg) + "℃ " + " 数据偏差: " + lib.To_string(math.Abs(originalAvg-目标originalAvg)) + "℃ " + " 设置:" + lib.To_string(T_deviation) + "℃" + " 冷点:" + Average_L.T_id + " 向上偏移0.1℃"}) originalAvg = Task.Read_TaskData_Average(Task_r.T_task_id, snList, 开始时间, 结束时间) originalAvg = RoundToDecimal(originalAvg, 1) } lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "" + " 温湿度绑定点1 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " + " 温湿度绑定点2 平均值:" + lib.To_string(温湿度绑定点2vga) + "℃ " + " 测点 平均值" + lib.To_string(originalAvg) + "℃ " + " 测点 最优平均值" + lib.To_string(目标originalAvg) + "℃ " + " 数据偏差: " + lib.To_string(RoundToDecimal(math.Abs(originalAvg-温湿度绑定点vga), 1)) + "℃ " + " 设置:" + lib.To_string(T_deviation) + "℃" + " 符合要求!"}) } // 向下偏移 if originalAvg > 目标originalAvg { for originalAvg > 目标originalAvg { // 热点向下偏移到高点范围 TaskData_Average_GroupBySnId := Task.Read_TaskData_Average_GroupBySnId(Task_r.T_task_id, snList, 开始时间, 结束时间) if len(TaskData_Average_GroupBySnId) == 0 { break } Average_H := TaskData_Average_GroupBySnId[0] T_max := Task.Read_TaskData_max(T_task_id, Average_H.T_sn, Average_H.T_id, 开始时间, 结束时间) T_min := Task.Read_TaskData_min(T_task_id, Average_H.T_sn, Average_H.T_id, 开始时间, 结束时间) c.SetAverageShiftedDownward(T_task_id, Average_H.T_id, T_deviation, RoundToDecimal(Average_H.Average-0.1, 1), Average_H.Average, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "") lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "" + " 温湿度绑定点1 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " + " 温湿度绑定点2 平均值:" + lib.To_string(温湿度绑定点2vga) + "℃ " + " 测点 平均值" + lib.To_string(originalAvg) + "℃ " + " 测点 最优平均值" + lib.To_string(目标originalAvg) + "℃ " + " 数据偏差: " + lib.To_string(math.Abs(originalAvg-目标originalAvg)) + "℃ " + " 设置:" + lib.To_string(T_deviation) + "℃" + " 冷点:" + Average_H.T_id + " 向下偏移0.1℃"}) originalAvg = Task.Read_TaskData_Average(Task_r.T_task_id, snList, 开始时间, 结束时间) originalAvg = RoundToDecimal(originalAvg, 1) } lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "" + " 温湿度绑定点1 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " + " 温湿度绑定点2 平均值:" + lib.To_string(温湿度绑定点2vga) + "℃ " + " 测点 平均值" + lib.To_string(originalAvg) + "℃ " + " 数据偏差: " + lib.To_string(RoundToDecimal(math.Abs(originalAvg-目标originalAvg), 1)) + "℃ " + " 设置:" + lib.To_string(T_deviation) + "℃" + " 符合要求!"}) } } } // 温控传感器绑定点 与 柜内所有测点|箱内所有测点|均匀性布点和产品存放区域测点 对比 ±1 T_deviation = 1 温控传感器绑定点_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "温控传感器绑定点1|温控传感器绑定点2") if len(温控传感器绑定点_list) == 0 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "没有找到温控传感器绑定点!"}) return } for i, classList := range 温控传感器绑定点_list { 温控传感器绑定点OriginalAvg := Task.Read_TaskData_Average(Task_r.T_task_id, classList.T_sn, 开始时间, 结束时间) 温控传感器绑定点OriginalAvg = RoundToDecimal(温控传感器绑定点OriginalAvg, 1) lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "------ 进行 温控传感器绑定点" + strconv.Itoa(i+1) + " 平均值处理 ------"}) if (温控传感器绑定点OriginalAvg >= originalAvg && 温控传感器绑定点OriginalAvg <= originalAvg+T_deviation) || (温控传感器绑定点OriginalAvg <= originalAvg && 温控传感器绑定点OriginalAvg >= originalAvg-T_deviation) { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: " 温控传感器绑定点" + lib.To_string(i+1) + " 平均值:" + lib.To_string(温控传感器绑定点OriginalAvg) + "℃ " + " 测点平均值" + lib.To_string(originalAvg) + "℃ " + " 数据偏差: " + lib.To_string(RoundToDecimal(math.Abs(温控传感器绑定点OriginalAvg-originalAvg), 1)) + "℃ " + " 设置:" + lib.To_string(T_deviation) + "℃" + " 符合要求!"}) } else { // 平均值最低点向上偏移 if 温控传感器绑定点OriginalAvg < originalAvg-T_deviation { for 温控传感器绑定点OriginalAvg < originalAvg-T_deviation { T_max := Task.Read_TaskData_max(T_task_id, classList.T_sn, classList.T_id, 开始时间, 结束时间) T_min := Task.Read_TaskData_min(T_task_id, classList.T_sn, classList.T_id, 开始时间, 结束时间) c.SetAverageShiftedUpward(T_task_id, classList.T_id, T_deviation, RoundToDecimal(温控传感器绑定点OriginalAvg+0.1, 1), 温控传感器绑定点OriginalAvg, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "") lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "温控传感器绑定点" + lib.To_string(i+1) + " 平均值:" + lib.To_string(温控传感器绑定点OriginalAvg) + "℃ " + "测点平均值" + lib.To_string(originalAvg) + "℃ " + "数据偏差: " + lib.To_string(RoundToDecimal(math.Abs(温控传感器绑定点OriginalAvg-originalAvg), 1)) + "℃ " + "设置:" + lib.To_string(T_deviation) + "℃" + "平均值向上偏移:0.1℃"}) 温控传感器绑定点OriginalAvg = Task.Read_TaskData_Average(Task_r.T_task_id, classList.T_sn, 开始时间, 结束时间) 温控传感器绑定点OriginalAvg = RoundToDecimal(温控传感器绑定点OriginalAvg, 1) } lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "温控传感器绑定点" + lib.To_string(i+1) + " 平均值:" + lib.To_string(温控传感器绑定点OriginalAvg) + "℃ " + "测点平均值" + lib.To_string(originalAvg) + "℃ " + "数据偏差: " + lib.To_string(RoundToDecimal(math.Abs(温控传感器绑定点OriginalAvg-originalAvg), 1)) + "℃ " + "设置:" + lib.To_string(T_deviation) + "℃" + "符合要求"}) continue } // 向下偏移 if 温控传感器绑定点OriginalAvg > originalAvg+T_deviation { for 温控传感器绑定点OriginalAvg > originalAvg+T_deviation { // 热点向下偏移到高点范围 T_max := Task.Read_TaskData_max(T_task_id, classList.T_sn, classList.T_id, 开始时间, 结束时间) T_min := Task.Read_TaskData_min(T_task_id, classList.T_sn, classList.T_id, 开始时间, 结束时间) c.SetAverageShiftedDownward(T_task_id, classList.T_id, T_deviation, RoundToDecimal(温控传感器绑定点OriginalAvg-0.1, 1), 温控传感器绑定点OriginalAvg, T_min, T_max, 温度控制范围最小值, 温度控制范围最高值, "", "") lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "温控传感器绑定点" + lib.To_string(i+1) + " 平均值:" + lib.To_string(温控传感器绑定点OriginalAvg) + "℃ " + "测点平均值" + lib.To_string(originalAvg) + "℃ " + "数据偏差: " + lib.To_string(RoundToDecimal(math.Abs(温控传感器绑定点OriginalAvg-originalAvg), 1)) + "℃ " + "设置:" + lib.To_string(T_deviation) + "℃" + "平均值向下偏移:0.1℃"}) 温控传感器绑定点OriginalAvg = Task.Read_TaskData_Average(Task_r.T_task_id, classList.T_sn, 开始时间, 结束时间) 温控传感器绑定点OriginalAvg = RoundToDecimal(温控传感器绑定点OriginalAvg, 1) } lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "温控传感器绑定点" + lib.To_string(i+1) + " 平均值:" + lib.To_string(温控传感器绑定点OriginalAvg) + "℃ " + "测点平均值" + lib.To_string(originalAvg) + "℃ " + "数据偏差: " + lib.To_string(RoundToDecimal(math.Abs(温控传感器绑定点OriginalAvg-originalAvg), 1)) + "℃ " + "设置:" + lib.To_string(T_deviation) + "℃" + "符合要求"}) } } } // ----------恢复保留数据------------ if Task_r.T_device_type != "X" { c.SaveRetainData(Task_r, 部点终端_list, valueStrings1, valueStrings2, 开空开, 开空开驼峰结束时间, 保空开, 保空开驼峰结束时间) } else { c.SaveBWXRetainData(Task_r, 部点终端_list, BWXValueStrings, 结束时间, 趋势时间, 60) } // ----------恢复保留数据结束------------ lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "完成!"}) // Close the connection c.Ctx.ResponseWriter.WriteHeader(http.StatusOK) } /* 平均值下移 targetAvg 参考平均值 originalAvg 原始平均值 T_min 整段数据最小值 T_max 整段数据最大值 minLimit 温度控制范围最小值 maxLimit 温度控制范围最大值 */ func (c *TaskDataHandleController) SetAverageShiftedDownward(T_task_id, T_id string, T_deviation, targetAvg, originalAvg, T_min, T_max, minLimit, maxLimit float64, StartTime, EndTime string) { 目标avg := RoundToDecimal(targetAvg+T_deviation, 1) vgaca := RoundToDecimal(originalAvg-目标avg, 1) //向下偏移后整段数据最小值大于温度控制范围最小值 if RoundToDecimal(T_min-vgaca, 1) > RoundToDecimal(minLimit, 1) && RoundToDecimal(T_max-vgaca, 1) < RoundToDecimal(maxLimit, 1) { Task.UpdateTaskDataTemperatureAndHumidityByGeometricAVG(T_task_id, T_id, "", "", -vgaca) lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + " 测点 " + lib.To_string(T_id) + " 最大值:" + lib.To_string(T_max) + "℃ " + " 最小值:" + lib.To_string(T_min) + "℃ " + " 参考平均值:" + lib.To_string(RoundToDecimal(targetAvg, 1)) + "℃ " + " 原始平均值:" + lib.To_string(RoundToDecimal(originalAvg, 1)) + "℃ " + " 数据偏差:" + lib.To_string(vgaca) + "℃ " + " 向下偏移:" + lib.To_string(vgaca) + "℃ "}) } else { compress1 := RoundToDecimal((minLimit+0.3-目标avg)/(T_min-originalAvg), 1) compress2 := RoundToDecimal((maxLimit-0.3-目标avg)/(T_max-originalAvg), 1) compress := math.Min(compress1, compress2) if RoundToDecimal(T_max*compress, 1) < maxLimit && RoundToDecimal(T_min*compress, 1) > minLimit { vgaca = 0 } else { vgaca = RoundToDecimal(目标avg-compress*originalAvg, 1) } lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + " 测点" + lib.To_string(T_id) + " 最大值:" + lib.To_string(T_max) + "℃ " + " 最小值:" + lib.To_string(T_min) + "℃ " + " 参考平均值:" + lib.To_string(RoundToDecimal(targetAvg, 1)) + "℃ " + " 原始平均值:" + lib.To_string(RoundToDecimal(originalAvg, 1)) + "℃ " + " 缩放:" + lib.To_string(compress) + " 缩放后最大值:" + lib.To_string(RoundToDecimal(T_max*compress, 1)) + "℃ " + " 缩放后最小值:" + lib.To_string(RoundToDecimal(T_min*compress, 1)) + "℃ " + " 数据偏差:" + lib.To_string(vgaca) + "℃ " + " 偏移:" + lib.To_string(vgaca) + "℃ "}) // 压缩 Task.UpdateTaskDataTemperatureAndHumidityByGeometric_id(T_task_id, T_id, "", "", compress) // 偏移 if vgaca != 0 { Task.UpdateTaskDataTemperatureAndHumidityByGeometricAVG(T_task_id, T_id, "", "", vgaca) } } } /* 平均值上移 targetAvg 参考平均值 originalAvg 原始平均值 T_min 整段数据最小值 T_max 整段数据最大值 minLimit 温度控制范围最小值 maxLimit 温度控制范围最大值 */ func (c *TaskDataHandleController) SetAverageShiftedUpward(T_task_id, T_id string, T_deviation, targetAvg, originalAvg, T_min, T_max, minLimit, maxLimit float64, StartTime, EndTime string) { 目标avg := RoundToDecimal(targetAvg-T_deviation, 1) vgaca := RoundToDecimal(目标avg-originalAvg, 1) if RoundToDecimal(T_max+vgaca, 1) < RoundToDecimal(maxLimit, 1) && RoundToDecimal(T_min+vgaca, 1) > RoundToDecimal(minLimit, 1) { Task.UpdateTaskDataTemperatureAndHumidityByGeometricAVG(T_task_id, T_id, "", "", vgaca) lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + " 测点 " + lib.To_string(T_id) + " 最大值:" + lib.To_string(T_max) + "℃ " + " 最小值:" + lib.To_string(T_min) + "℃ " + " 参考平均值:" + lib.To_string(RoundToDecimal(targetAvg, 1)) + "℃ " + " 原始平均值:" + lib.To_string(RoundToDecimal(originalAvg, 1)) + "℃ " + " 数据偏差:" + lib.To_string(vgaca) + "℃ " + " 向上偏移:" + lib.To_string(vgaca) + "℃ "}) } else { compress1 := RoundToDecimal((minLimit+0.3-目标avg)/(T_min-originalAvg), 1) compress2 := RoundToDecimal((maxLimit-0.3-目标avg)/(T_max-originalAvg), 1) compress := math.Min(compress1, compress2) if RoundToDecimal(T_max*compress, 1) < maxLimit && RoundToDecimal(T_min*compress, 1) > minLimit { vgaca = 0 } else { vgaca = RoundToDecimal(目标avg-compress*originalAvg, 1) } lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + " 测点" + lib.To_string(T_id) + " 最大值:" + lib.To_string(T_max) + "℃ " + " 最小值:" + lib.To_string(T_min) + "℃ " + " 参考平均值:" + lib.To_string(RoundToDecimal(targetAvg, 1)) + "℃ " + " 原始平均值:" + lib.To_string(RoundToDecimal(originalAvg, 1)) + "℃ " + " 缩放:" + lib.To_string(compress) + " 缩放后最大值:" + lib.To_string(RoundToDecimal(T_max*compress, 1)) + "℃ " + " 缩放后最小值:" + lib.To_string(RoundToDecimal(T_min*compress, 1)) + "℃ " + " 数据偏差:" + lib.To_string(vgaca) + "℃ " + " 偏移:" + lib.To_string(vgaca) + "℃ "}) // 压缩 Task.UpdateTaskDataTemperatureAndHumidityByGeometric_id(T_task_id, T_id, "", "", compress) // 偏移 if vgaca != 0 { Task.UpdateTaskDataTemperatureAndHumidityByGeometricAVG(T_task_id, T_id, "", "", vgaca) } } } func (c *TaskDataHandleController) GetMetadata(T_task_id, SN, startTime string) (valueStrings []string, endTime string) { list := Task.Read_TaskData_ById_AVG(T_task_id, SN, startTime, "") // 获取第一个驼峰结束时间点 CalculateHumps_list := Task.CalculateHumpsByThreeDots(list) if len(CalculateHumps_list) < 1 { return } endTime = CalculateHumps_list[0].End.T_time data1, _ := Task.Read_TaskData_ById_List_AES(T_task_id, SN, "", startTime, endTime, 0, 9999) for _, v := range data1 { 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)) } return valueStrings, endTime } // 获取保留数据 func (c *TaskDataHandleController) GetRetainData(Task_r Task.Task, SN string) (valueStrings1, valueStrings2 []string, kkkStartTime, kkkEndTime, bkkStartTime, bkkEndTime string) { var 开空开, 保空开, 开空开驼峰结束时间, 保空开驼峰结束时间 string if Task_r.T_device_type != "X" { 开空开 = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "开空开") if len(开空开) == 0 { 开空开 = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "开满开") } if len(开空开) == 0 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 开空开/开满开 时间 标签!"}) return } 保空开 = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "保空开") if len(保空开) == 0 { 保空开 = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "保满开") } if len(保空开) == 0 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 保空开/保满开 时间 标签!"}) return } valueStrings1, 开空开驼峰结束时间 = c.GetMetadata(Task_r.T_task_id, SN, 开空开) valueStrings2, 保空开驼峰结束时间 = c.GetMetadata(Task_r.T_task_id, SN, 保空开) } return valueStrings1, valueStrings2, 开空开, 开空开驼峰结束时间, 保空开, 保空开驼峰结束时间 } // 获取保留数据 func (c *TaskDataHandleController) SaveRetainData(Task_r Task.Task, SN_list []Device.DeviceClassList, valueStrings1, valueStrings2 []string, kkkStartTime, kkkEndTime, bkkStartTime, bkkEndTime string) { var err error if len(valueStrings1) > 0 { //将开空开/开满开时间开始第一个驼峰 写入原始数据 for _, device := range SN_list { Task.DeleteTaskDataByTimeRange(Task_r.T_task_id, device.T_sn, device.T_id, kkkStartTime, kkkEndTime) } err = Task.Batch_Adds_TaskData(Task_r.T_task_id, valueStrings1) if err == nil { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: fmt.Sprintf("恢复开空开/开满开时间点后驼峰 %s ~ %s 数据 %d/%d", kkkStartTime, kkkEndTime, len(valueStrings1), len(valueStrings1))}) } } if len(valueStrings2) > 0 { //将开空开/开满开时间开始第一个驼峰 写入原始数据 for _, device := range SN_list { Task.DeleteTaskDataByTimeRange(Task_r.T_task_id, device.T_sn, device.T_id, bkkStartTime, bkkEndTime) } err = Task.Batch_Adds_TaskData(Task_r.T_task_id, valueStrings2) if err == nil { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: fmt.Sprintf("恢复保空开/保满开时间点后驼峰 %s ~ %s 数据 %d/%d", bkkStartTime, bkkEndTime, len(valueStrings2), len(valueStrings2))}) } } } func (c *TaskDataHandleController) GetBWXRetainData(Task_r Task.Task, SN string, endTime, trendTime string) (BWXValueStrings []string) { if endTime != trendTime { data1, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, SN, "", trendTime, "", 0, 9999) for _, v := range data1 { 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)) } } return } func (c *TaskDataHandleController) SaveBWXRetainData(Task_r Task.Task, SN_list []Device.DeviceClassList, BWXValueStrings []string, endTime, trendTime string, saveTime int) { var err error if endTime != trendTime && len(BWXValueStrings) > 0 { //将开空开/开满开时间开始第一个驼峰 写入原始数据 for _, device := range SN_list { Task.DeleteTaskDataByTimeRange(Task_r.T_task_id, device.T_sn, device.T_id, trendTime, "") } err = Task.Batch_Adds_TaskData(Task_r.T_task_id, BWXValueStrings) if err == nil { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: fmt.Sprintf("恢复 保温箱 原始数据 %d/%d", len(BWXValueStrings), len(BWXValueStrings))}) } var startTime string startTime = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "静态开箱作业开箱结束时间") if len(startTime) == 0 { startTime = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "动态开箱作业开箱结束时间") } if len(startTime) == 0 { startTime = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "开箱作业开箱结束时间") } if len(startTime) == 0 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 静态开箱作业开箱结束时间|动态开箱作业开箱结束时间|开箱作业开箱结束时间 失败"}) return } startTimeT, _ := lib.TimeStrToTime(startTime) startTime = startTimeT.Add(30 * time.Minute).Format("2006-01-02 15:04") // 执行数据平滑 for _, v := range SN_list { sn := v.T_sn id_str := v.T_id list, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, sn, id_str, startTime, trendTime, 0, 9999) first := list[0] last := list[len(list)-1] current, _ := time.Parse("2006-01-02 15:04", first.T_time) next, _ := time.Parse("2006-01-02 15:04", last.T_time) interval := next.Sub(current).Seconds() / float64(saveTime) ttInterval := (last.T_t - first.T_t) / float32(interval) trhInterval := (last.T_rh - first.T_rh) / float32(interval) tt := first.T_t ttrh := first.T_rh var valueStrings []string for current.Unix() < next.Unix() { tt += ttInterval ttrh += trhInterval ttime := current.Format("2006-01-02 15:04") valueStrings = append(valueStrings, fmt.Sprintf("('%s','%s',%v,%v,'%s')", first.T_sn, id_str, tt, ttrh, ttime)) current = current.Add(time.Second * time.Duration(saveTime)) } Task.DeleteTaskDataByTimeRange(Task_r.T_task_id, sn, id_str, startTime, trendTime) err = Task.Batch_Adds_TaskData(Task_r.T_task_id, valueStrings) if err == nil { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: fmt.Sprintf("保温箱数据趋势 %d/%d", len(valueStrings), len(valueStrings))}) } } } } // 获取开始结束时间 func (c *TaskDataHandleController) GetStartTimeAndEndTime(Task_r Task.Task, SN string, maxLimit float64) (startTime, endTime, trendTime string) { // 开始时间 获取温度下降到第二个低点时间 // 1. 获取温度平均值 list := Task.Read_TaskData_ById_AVG(Task_r.T_task_id, SN, "", "") if len(list) < 2 { lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "均匀性布点+产品存放区域测点+作业出入口总测点 数据平均值 少于2条!"}) return } // 找平均值低于温度控制范围最高值的第二个最低点 lowPoint := 0 for i := 1; i <= len(list)-2; i++ { 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) { lowPoint += 1 } if lowPoint == 2 { startTime = list[i].T_time break } } // 保温箱没有开空开,开满开 // 结束时间温度超限取没有超限时间点,结束时间温度未超限取最后一个时间点 if Task_r.T_device_type == "X" { list2 := Task.Read_TaskData_ById_AVG_DESC(Task_r.T_task_id, SN, "", "") if len(list) == 0 { return } if float64(list2[0].T_t) < maxLimit { endTime = list2[0].T_time trendTime = list2[0].T_time return } for i, avg := range list2 { if RoundToDecimal(float64(avg.T_t), 1) < maxLimit { endTime = avg.T_time trendTime = list2[i-1].T_time break } } } else { endTime = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "开空开") if len(endTime) == 0 { endTime = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "开满开") } if len(endTime) == 0 { endTime = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "现场测试结束时间") } if len(endTime) == 0 { return } } return } /* 计算绑定点的值 A 监测终端01平均值 B 监测终端02平均值 C 温湿度绑定点01平均值 D 温湿度绑定点02平均值 */ func findBindingPointsOptimalAdjustment(A, B, C, D, T_deviation float64) (float64, float64, bool) { type DataPair struct { A1 float64 B1 float64 } T_deviation_half := 0.1 var dataPairs []DataPair var A1, B1 float64 = -100, -100 // 生成A1和B1的可能值 for a1 := A - T_deviation; a1 <= A+T_deviation; a1 += T_deviation_half { for b1 := B - T_deviation; b1 <= B+T_deviation; b1 += T_deviation_half { // 检查是否存在满足条件的C值 minC := math.Max(a1-T_deviation_half, b1-T_deviation_half) maxC := math.Min(a1+T_deviation_half, b1+T_deviation_half) if minC <= maxC { dataPairs = append(dataPairs, DataPair{A1: a1, B1: b1}) } } } if len(dataPairs) == 1 { A1 = dataPairs[0].A1 B1 = dataPairs[0].B1 } if len(dataPairs) > 1 { // 寻找最优解 minAdjustment := math.MaxFloat64 var optimalPair DataPair for _, pair := range dataPairs { adjustment := math.Abs(pair.A1-C) + math.Abs(pair.B1-D) if adjustment < minAdjustment { minAdjustment = adjustment optimalPair = pair } } A1 = optimalPair.A1 B1 = optimalPair.B1 } if A1 == -100 || B1 == -100 { return A1, B1, false } return A1, B1, true } /* 计算绑定点的值 A 温湿度绑定点1平均值 B 温湿度绑定点2平均值 C 测点平均值 */ func findAverageOptimalAdjustment(A, B, C float64) float64 { // 计算有效区间 minA := A - 0.5 maxA := A + 0.5 minB := B - 0.5 maxB := B + 0.5 // 求交集范围 lowerBound := math.Max(minA, minB) upperBound := math.Min(maxA, maxB) // 确定最优调整值 var optimalC float64 if C < lowerBound { optimalC = lowerBound // 取区间下限 } else if C > upperBound { optimalC = upperBound // 取区间上限 } else { optimalC = C // 已在区间内无需调整 } return optimalC }