Prechádzať zdrojové kódy

update:布点数据自检

zoie 2 týždňov pred
rodič
commit
c46507c901

+ 82 - 79
controllers/TaskData.go

@@ -1658,17 +1658,22 @@ func (c *TaskDataController) CopyFromPosition() {
 		List, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, sn, id_str, StartTime, EndTime, 0, 9999)
 		Task.DeleteTaskDataByTimeRange(Task_r.T_task_id, sn, id_str, CopyTime, CopyEndTime)
 		ct := copyTime
-		go func(TaskDataList []Task.TaskData_, task_id string, T_saveT int) {
-			for _, taskData := range TaskDataList {
-				taskData.T_time = ct.Format("2006-01-02 15:04:05")
-				Task.InsertTaskData(task_id, taskData)
-				ct = ct.Add(time.Second * time.Duration(T_saveT))
-			}
-		}(List, Task_r.T_task_id, T_saveT)
+		var valueStrings []string
+		for _, data := range List {
+			valueStrings = append(valueStrings, fmt.Sprintf("('%s','%s',%v,%v,'%s')", data.T_sn, data.T_id, data.T_t, data.T_rh, ct.Format("2006-01-02 15:04:05")))
+			ct = ct.Add(time.Second * time.Duration(T_saveT))
+		}
+		err = Task.Batch_Adds_TaskData(T_task_id, valueStrings)
+		if err != nil {
+			c.Data["json"] = lib.JSONS{Code: 202, Msg: "数据复制失败!" + err.Error()}
+			c.ServeJSON()
+			return
+		}
+
 	}
 	System.Add_UserLogs_T(T_uuid, "数据复制", fmt.Sprintf("数据复制(%s)[%s|%s],复制时间:%s,,时间间隔:%d", T_task_id, StartTime, EndTime, CopyTime, T_saveT), SN_List)
 
-	c.Data["json"] = lib.JSONS{200, "数据复制已提交后台处理!", nil}
+	c.Data["json"] = lib.JSONS{200, "数据复制已完成!", nil}
 	c.ServeJSON()
 	return
 }
@@ -1826,22 +1831,22 @@ func (c *TaskDataController) DataSensorDataTrend() {
 		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:05")
-
-			Task.InsertTaskData(Task_r.T_task_id, Task.TaskData_{
-				//加保存时间
-				T_sn:   first.T_sn,
-				T_id:   id_str,
-				T_t:    tt,
-				T_rh:   ttrh,
-				T_time: ttime,
-			})
+			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))
 		}
 
+		err = Task.Batch_Adds_TaskData(T_task_id, valueStrings)
+		if err != nil {
+			c.Data["json"] = lib.JSONS{Code: 202, Msg: "数据复制失败!" + err.Error()}
+			c.ServeJSON()
+			return
+		}
+
 	}
 	System.Add_UserLogs_T(T_uuid, "数据趋势", fmt.Sprintf("数据趋势(%s)[%s|%s],时间间隔:%d", T_task_id, StartTime, EndTime, saveTime), SN_List)
 
@@ -2229,19 +2234,21 @@ func (c *TaskDataController) CopyFromPositionSN() {
 	List, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, sn, id_str, StartTime, EndTime, 0, 9999)
 	Task.DeleteTaskDataByTimeRange(Task_r.T_task_id, CopySN, CopyID, CopyTime, CopyEndTime)
 	ct := copyTime
-	go func(TaskDataList []Task.TaskData_, task_id string, T_saveT int) {
-		for _, taskData := range TaskDataList {
-			taskData.T_time = ct.Format("2006-01-02 15:04:05")
-			taskData.T_sn = CopySN
-			taskData.T_id = CopyID
-			Task.InsertTaskData(task_id, taskData)
-			ct = ct.Add(time.Second * time.Duration(T_saveT))
-		}
-	}(List, Task_r.T_task_id, T_saveT)
+	var valueStrings []string
+	for _, data := range List {
+		valueStrings = append(valueStrings, fmt.Sprintf("('%s','%s',%v,%v,'%s')", CopySN, CopyID, data.T_t, data.T_rh, ct.Format("2006-01-02 15:04:05")))
+		ct = ct.Add(time.Second * time.Duration(T_saveT))
+	}
+	err = Task.Batch_Adds_TaskData(T_task_id, valueStrings)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "数据拷贝失败!" + err.Error()}
+		c.ServeJSON()
+		return
+	}
 
-	System.Add_UserLogs_T(T_uuid, "数据复制", fmt.Sprintf("数据复制(%s)[%s|%s],复制时间:%s,,时间间隔:%d", T_task_id, StartTime, EndTime, CopyTime, T_saveT), SN_List)
+	System.Add_UserLogs_T(T_uuid, "数据拷贝", fmt.Sprintf("数据拷贝(%s)[%s|%s],拷贝时间:%s,,时间间隔:%d", T_task_id, StartTime, EndTime, CopyTime, T_saveT), SN_List)
 
-	c.Data["json"] = lib.JSONS{200, "数据复制已提交后台处理!", nil}
+	c.Data["json"] = lib.JSONS{200, "数据拷贝已完成!", nil}
 	c.ServeJSON()
 	return
 }
@@ -3015,7 +3022,7 @@ func (c *TaskDataController) A满载测试结束风机停止时间() {
 
 	// 获取数据波动最大的三条
 	initialData, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, 均匀性布点, "", 开始时间, 结束时间, 0, 9999)
-	snList := Task.GetTopThreeWithTheGreatestFluctuations(initialData)
+	snList := Task.GetTheGreatestFluctuations(initialData, 3)
 
 	list := Task.Read_TaskData_ById_AVG(Task_r.T_task_id, snList, 开始时间, 结束时间)
 	fmt.Println("list:", list)
@@ -3080,7 +3087,7 @@ func (c *TaskDataController) A空载测试结束风机停止时间() {
 
 	// 获取数据波动最大的三条
 	initialData, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, 均匀性布点, "", 开始时间, 结束时间, 0, 9999)
-	snList := Task.GetTopThreeWithTheGreatestFluctuations(initialData)
+	snList := Task.GetTheGreatestFluctuations(initialData, 3)
 	list := Task.Read_TaskData_ById_AVG(Task_r.T_task_id, snList, 开始时间, 结束时间)
 	CalculateHumps_list := Task.CalculateHumps(list)
 
@@ -3137,7 +3144,7 @@ func (c *TaskDataController) A满载风机停止时间点() {
 	}
 
 	initialData, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, 均匀性布点, "", 开始时间, 结束时间, 0, 9999)
-	snList := Task.GetTopThreeWithTheGreatestFluctuations(initialData)
+	snList := Task.GetTheGreatestFluctuations(initialData, 3)
 	list := Task.Read_TaskData_ById_AVG(Task_r.T_task_id, snList, 开始时间, 结束时间)
 	CalculateHumps_list := Task.CalculateHumps(list)
 
@@ -3194,7 +3201,7 @@ func (c *TaskDataController) A空载风机停止时间点() {
 	}
 
 	initialData, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, 均匀性布点, "", 开始时间, 结束时间, 0, 9999)
-	snList := Task.GetTopThreeWithTheGreatestFluctuations(initialData)
+	snList := Task.GetTheGreatestFluctuations(initialData, 3)
 	list := Task.Read_TaskData_ById_AVG(Task_r.T_task_id, snList, 开始时间, 结束时间)
 	CalculateHumps_list := Task.CalculateHumps(list)
 
@@ -3250,7 +3257,7 @@ func (c *TaskDataController) A空载风机启动时间点() {
 	}
 
 	initialData, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, 均匀性布点, "", 开始时间, 结束时间, 0, 9999)
-	snList := Task.GetTopThreeWithTheGreatestFluctuations(initialData)
+	snList := Task.GetTheGreatestFluctuations(initialData, 3)
 	list := Task.Read_TaskData_ById_AVG(Task_r.T_task_id, snList, 开始时间, 结束时间)
 	CalculateHumps_list := Task.CalculateHumps(list)
 
@@ -3306,7 +3313,7 @@ func (c *TaskDataController) A满载风机启动时间点() {
 	}
 
 	initialData, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, 均匀性布点, "", 开始时间, 结束时间, 0, 9999)
-	snList := Task.GetTopThreeWithTheGreatestFluctuations(initialData)
+	snList := Task.GetTheGreatestFluctuations(initialData, 3)
 	list := Task.Read_TaskData_ById_AVG(Task_r.T_task_id, snList, 开始时间, 结束时间)
 	CalculateHumps_list := Task.CalculateHumps(list)
 
@@ -4271,7 +4278,7 @@ func (c *TaskDataController) A温度分布特性开始时间() {
 }
 
 // 箱内所有测点|温度自动监测设备放置位置开始时间
-// 1}取 平均值 ,高于等于 [温度范围最高值] 并持续5分钟,取 第一个超标时的时间值
+// 1}取 平均值 ,高于等于 [温度控制范围最高值] 并持续5分钟,取 第一个超标时的时间值
 // 2}[温湿度系统测点] 取最后时间点
 func (c *TaskDataController) A温度自动监测设备放置位置结束时间() {
 
@@ -4297,12 +4304,12 @@ func (c *TaskDataController) A温度自动监测设备放置位置结束时间()
 		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 温度自动监测设备放置位置开始时间 失败!"})
 		return
 	}
-	温度范围最高值_ := c.GetString("温度范围最高值") //  v26nplogbwt1
-	if len(温度范围最高值_) == 0 {
-		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 温度范围最高值 失败!"})
+	温度控制范围最高值_ := c.GetString("温度控制范围最高值") //  v26nplogbwt1
+	if len(温度控制范围最高值_) == 0 {
+		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 温度控制范围最高值 失败!"})
 		return
 	}
-	温度范围最高值 := lib.To_float32(温度范围最高值_)
+	温度控制范围最高值 := lib.To_float32(温度控制范围最高值_)
 
 	list := Task.Read_TaskData_ById_AVG(Task_r.T_task_id, 箱内所有测点, 温度自动监测设备放置位置开始时间, "")
 	if len(list) == 0 {
@@ -4311,7 +4318,7 @@ func (c *TaskDataController) A温度自动监测设备放置位置结束时间()
 	}
 
 	for i := 0; i < (len(list) - 7); i++ {
-		if list[i].T_t >= 温度范围最高值 {
+		if list[i].T_t >= 温度控制范围最高值 {
 			if list[i].T_t <= list[i+1].T_t &&
 				list[i+1].T_t <= list[i+2].T_t &&
 				list[i+2].T_t <= list[i+3].T_t &&
@@ -4324,7 +4331,7 @@ func (c *TaskDataController) A温度自动监测设备放置位置结束时间()
 		}
 	}
 
-	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "没找到 高于等于 [温度范围最高值] 并持续5分钟 数据!"})
+	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "没找到 高于等于 [温度控制范围最高值] 并持续5分钟 数据!"})
 	// Close the connection
 	c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
 }
@@ -4381,7 +4388,7 @@ func (c *TaskDataController) A保温箱准备开始时间() {
 }
 
 // 箱内所有测点|现场测试开始时间|温度自动监测设备放置位置开始时间
-// 温度低于(温度范围最高值 - 0.5),= 低于温度当前时的时间点
+// 温度低于(温度控制范围最高值 - 0.5),= 低于温度当前时的时间点
 func (c *TaskDataController) A冰排预冷保温箱准备结束时间() {
 
 	T_task_id := c.GetString("T_task_id") //  v26nplogbwt1
@@ -4411,15 +4418,15 @@ func (c *TaskDataController) A冰排预冷保温箱准备结束时间() {
 	//	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 温度自动监测设备放置位置开始时间 失败!"})
 	//	return
 	//}
-	温度范围最高值_ := c.GetString("温度范围最高值") //  v26nplogbwt1
-	if len(温度范围最高值_) == 0 {
-		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 温度范围最高值 失败!"})
+	温度控制范围最高值_ := c.GetString("温度控制范围最高值") //  v26nplogbwt1
+	if len(温度控制范围最高值_) == 0 {
+		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 温度控制范围最高值 失败!"})
 		return
 	}
-	温度范围最高值 := lib.To_float32(温度范围最高值_) - 0.5
-	list, _ := Task.Read_TaskData_ById_List_SQL(Task_r.T_task_id, " AND t_t  <= "+lib.To_string(温度范围最高值)+" ", 箱内所有测点, "", 现场测试开始时间, "", 0, 1)
+	温度控制范围最高值 := lib.To_float32(温度控制范围最高值_) - 0.5
+	list, _ := Task.Read_TaskData_ById_List_SQL(Task_r.T_task_id, " AND t_t  <= "+lib.To_string(温度控制范围最高值)+" ", 箱内所有测点, "", 现场测试开始时间, "", 0, 1)
 	if len(list) == 0 {
-		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "没找到 温度低于(温度范围最高值 - 0.5) !"})
+		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "没找到 温度低于(温度控制范围最高值 - 0.5) !"})
 		return
 	}
 
@@ -4428,7 +4435,7 @@ func (c *TaskDataController) A冰排预冷保温箱准备结束时间() {
 	c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
 }
 
-// 保温箱温度设定值 = (温度范围最高值 - 温度范围最低值)/ 2
+// 保温箱温度设定值 = (温度控制范围最高值 - 温度范围最低值)/ 2
 func (c *TaskDataController) A保温箱温度设定值() {
 
 	T_task_id := c.GetString("T_task_id") //  v26nplogbwt1
@@ -4437,8 +4444,8 @@ func (c *TaskDataController) A保温箱温度设定值() {
 	c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
 	c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
 
-	温度范围最高值 := c.GetString("温度控制范围最高值") //  v26nplogbwt1
-	if len(温度范围最高值) == 0 {
+	温度控制范围最高值 := c.GetString("温度控制范围最高值") //  v26nplogbwt1
+	if len(温度控制范围最高值) == 0 {
 		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 温度控制范围最高值 失败!"})
 		return
 	}
@@ -4448,7 +4455,7 @@ func (c *TaskDataController) A保温箱温度设定值() {
 		return
 	}
 
-	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: lib.To_string((lib.To_float32(温度范围最高值) + lib.To_float32(温度范围最低值)) / 2)})
+	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: lib.To_string((lib.To_float32(温度控制范围最高值) + lib.To_float32(温度范围最低值)) / 2)})
 	// Close the connection
 	c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
 }
@@ -5042,13 +5049,13 @@ func (c *TaskDataController) A内部环境分割线最高温() {
 	c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
 	c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
 
-	温度范围最高值 := c.GetString("温度控制范围最高值") //  v26nplogbwt1
-	if len(温度范围最高值) == 0 {
+	温度控制范围最高值 := c.GetString("温度控制范围最高值") //  v26nplogbwt1
+	if len(温度控制范围最高值) == 0 {
 		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 温度控制范围最高值 失败!"})
 		return
 	}
 
-	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: 温度范围最高值})
+	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: 温度控制范围最高值})
 
 	// Close the connection
 	c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
@@ -6110,18 +6117,16 @@ func (c *TaskDataController) A监测终端01() {
 		return
 	}
 
-	DeviceClassList_r := Device.Read_DeviceClassList_List_id(Task_r.T_class)
-	for _, v := range DeviceClassList_r {
-		if strings.Contains(v.T_sn, "-1") {
-			lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: v.T_sn})
+	监测终端_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: 1, Msg: 监测终端_list[0].T_sn})
 
-			// Close the connection
-			c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
-			return
-		}
+		// Close the connection
+		c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
+		return
 	}
 
-	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "没有找到 SN-1 终端!"})
+	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "没有找到 终端01 !"})
 	return
 
 }
@@ -6139,15 +6144,13 @@ func (c *TaskDataController) A监测终端安装编号01() {
 		return
 	}
 
-	DeviceClassList_r := Device.Read_DeviceClassList_List_id(Task_r.T_class)
-	for _, v := range DeviceClassList_r {
-		if strings.Contains(v.T_sn, "-1") {
-			lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: v.T_sn})
+	监测终端_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: 1, Msg: 监测终端_list[0].T_sn})
 
-			// Close the connection
-			c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
-			return
-		}
+		// Close the connection
+		c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
+		return
 	}
 
 	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "没有找到 SN-1 终端!"})
@@ -6416,8 +6419,8 @@ func (c *TaskDataController) A风机布点总测点() {
 	c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
 	c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
 
-	一号风机测点 := c.GetString("1号风机测点")     //  v26nplogbwt1
-	二号风机测点 := c.GetString("2号风机测点")     //  v26nplogbwt1
+	一号风机测点 := c.GetString("1号风机测点")   //  v26nplogbwt1
+	二号风机测点 := c.GetString("2号风机测点")   //  v26nplogbwt1
 	一号风机回风口 := c.GetString("1号风机回风口") //  v26nplogbwt1
 	二号风机回风口 := c.GetString("2号风机回风口") //  v26nplogbwt1
 
@@ -6445,7 +6448,7 @@ func (c *TaskDataController) A库内除风机出风口回风口外总测点() {
 	c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
 	c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
 
-	库内所有测点 := c.GetString("库内所有测点")     //  v26nplogbwt1
+	库内所有测点 := c.GetString("库内所有测点")   //  v26nplogbwt1
 	风机布点总测点 := c.GetString("风机布点总测点") //  v26nplogbwt1
 
 	parts1 := strings.Split(库内所有测点, "|")
@@ -6476,9 +6479,9 @@ func (c *TaskDataController) A库内除风机出风口回风口特殊位置布
 	c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
 	c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
 
-	库内所有测点 := c.GetString("库内所有测点")                                           //  v26nplogbwt1
-	风机布点总测点 := c.GetString("风机布点总测点")                                       //  v26nplogbwt1
-	作业出入口总测点 := c.GetString("作业出入口总测点")                                   //  v26nplogbwt1
+	库内所有测点 := c.GetString("库内所有测点")                       //  v26nplogbwt1
+	风机布点总测点 := c.GetString("风机布点总测点")                     //  v26nplogbwt1
+	作业出入口总测点 := c.GetString("作业出入口总测点")                   //  v26nplogbwt1
 	照明灯除湿机风幕机等特殊区域测点 := c.GetString("照明灯、除湿机、风幕机等特殊区域测点") //  v26nplogbwt1
 
 	parts1 := strings.Split(strings.Trim(库内所有测点, "|"), "|")
@@ -6517,7 +6520,7 @@ func (c *TaskDataController) A车内除风机出风口回风口外总测点() {
 	c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
 	c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
 
-	车内所有测点 := c.GetString("车内所有测点")     //  v26nplogbwt1
+	车内所有测点 := c.GetString("车内所有测点")   //  v26nplogbwt1
 	风机布点总测点 := c.GetString("风机布点总测点") //  v26nplogbwt1
 
 	parts1 := strings.Split(车内所有测点, "|")

+ 424 - 374
controllers/TaskHandle.go

@@ -24,7 +24,7 @@ type TaskDataHandleController struct {
 同区域数据缺失
 */
 
-// 自动添加缺失终端,取关联绑定终端平均复制
+// 测点自检 自动添加缺失终端,取关联绑定终端平均复制
 func (c *TaskDataHandleController) SSE_Automatically_add_missing_terminal() {
 
 	T_task_id := c.GetString("T_task_id") //  v26nplogbwt1
@@ -133,8 +133,8 @@ func (c *TaskDataHandleController) SSE_Automatically_add_missing_terminal() {
 			if len(List2) < len(List1) {
 				num = len(List2)
 			}
-			var list []Task.TaskData_
 			ct := copyTime
+			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)})
@@ -142,22 +142,16 @@ func (c *TaskDataHandleController) SSE_Automatically_add_missing_terminal() {
 				}
 				T_t := (List1[i].T_t + List2[i].T_t) / 2
 				T_rh := (List1[i].T_rh + List2[i].T_rh) / 2
-				list = append(list, Task.TaskData_{
-					T_sn:   CopySN,
-					T_id:   CopyID,
-					T_t:    T_t,
-					T_rh:   T_rh,
-					T_time: ct.Format("2006-01-02 15:04:05"),
-				})
+
+				valueStrings = append(valueStrings, fmt.Sprintf("('%s','%s',%v,%v,'%s')", CopySN, CopyID, T_t, T_rh, ct.Format("2006-01-02 15:04:05")))
+
 				ct = ct.Add(time.Second * time.Duration(T_saveT))
 			}
 			Task.DeleteTaskDataByTimeRange(Task_r.T_task_id, CopySN, CopyID, CopyTime, CopyEndTime)
-			for i, taskData := range list {
-				Task.InsertTaskData(Task_r.T_task_id, taskData)
 
-				if i%100 == 0 {
-					lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: fmt.Sprintf("%d/%d", i, len(list))})
-				}
+			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))})
 			}
 
 		}
@@ -169,7 +163,7 @@ func (c *TaskDataHandleController) SSE_Automatically_add_missing_terminal() {
 	c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
 }
 
-// 自动添加缺失数据,取关联绑定终端平均复制
+// 测点数据自检 自动添加缺失数据,取关联绑定终端平均复制
 func (c *TaskDataHandleController) SSE_Automatically_add_missing_data() {
 
 	T_task_id := c.GetString("T_task_id") //  v26nplogbwt1
@@ -198,6 +192,7 @@ func (c *TaskDataHandleController) SSE_Automatically_add_missing_data() {
 		if Devicedata_list_MAX < cnt {
 			Devicedata_list_MAX = cnt
 		}
+
 	}
 	logs.Println("数据标准数量:", Devicedata_list_MAX)
 	// 选择 数据缺失的终端
@@ -214,6 +209,23 @@ func (c *TaskDataHandleController) SSE_Automatically_add_missing_data() {
 				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: "找到自检点 " + current + " ~ " + next + " 开始自检"})
+
+					t := ct.Add(time.Second * time.Duration(T_saveT)).Format("2006-01-02 15:04:05") //时间临时变量
+					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: "找到自检点 " + current + " ~ " + next + " 开始自检"})
 
@@ -231,97 +243,40 @@ func (c *TaskDataHandleController) SSE_Automatically_add_missing_data() {
 						}
 					}
 					// 筛选 符合的数量 终端
-					SN_List_sn := 9
-					SN_List_s := "" // 2023282551724643,003|2023282534778895,004|
-					SN_List_xn := 9
-					SN_List_x := "" // 2023282551724643,003|2023282534778895,004|
-					SN_List := ""   // 2023282551724643,003|2023282534778895,004|
+					//SN_List_sn := 9
+					//SN_List_s := "" // 2023282551724643,003|2023282534778895,004|
+					//SN_List_xn := 9
+					//SN_List_x := "" // 2023282551724643,003|2023282534778895,004|
+					SN_List := "" // 2023282551724643,003|2023282534778895,004|
 					//SN_List_num := 0     // 数量  只能两个
 					CopyTime := current  //复制的起点 2025-01-07 15:18:00
 					StartTime := current // 2025-01-07 15:18:00
 					EndTime := next      //2025-01-07 21:17:00
-					for _, DeviceClassListT_remark_r_list := range DeviceClassListT_remark_r {
-						List_data, cnt := Task.Read_TaskData_ById_List(Task_r.T_task_id, DeviceClassListT_remark_r_list.T_sn, DeviceClassListT_remark_r_list.T_id, "", "", 0, 9999)
-						if DeviceClassListT_remark_r_list_MAX == cnt {
-							logs.Println(DeviceClassListT_remark_r_list.T_sn, DeviceClassListT_remark_r_list.T_id, "数量:", cnt)
-							//SN_List += DeviceClassListT_remark_r_list.T_sn + "," + DeviceClassListT_remark_r_list.T_id + "|"
-							//CopyTime = List_data[len(List_data)-1].T_time
-							//StartTime = List_data[len(List_data)-1].T_time
+					var completeDataDeviceClassList []Device.DeviceClassList
+					for _, DeviceClassList := range DeviceClassListT_remark_r {
+						List_data, count := Task.Read_TaskData_ById_List(Task_r.T_task_id, DeviceClassList.T_sn, DeviceClassList.T_id, "", "", 0, 9999)
+						if DeviceClassListT_remark_r_list_MAX == count {
+							logs.Println(DeviceClassList.T_sn, DeviceClassList.T_id, "数量:", cnt)
 							EndTime = List_data[0].T_time
-
-							absc := int(math.Abs(float64(lib.To_int(DeviceClassListT_remark_r_list.T_id) - lib.To_int(DeviceClassList_r.T_id))))
-
-							if absc < SN_List_sn {
-								SN_List_s = DeviceClassListT_remark_r_list.T_sn + "," + DeviceClassListT_remark_r_list.T_id + "|"
-								SN_List_sn = absc
-								continue
-							}
-							if absc < SN_List_xn {
-								SN_List_x = DeviceClassListT_remark_r_list.T_sn + "," + DeviceClassListT_remark_r_list.T_id + "|"
-								SN_List_xn = absc
-								continue
-							}
-
+							completeDataDeviceClassList = append(completeDataDeviceClassList, DeviceClassList)
 						}
 					}
+
 					logs.Println("复制参数:", SN_List, CopyTime, StartTime, EndTime)
-					if len(SN_List_x) == 0 || len(SN_List_s) == 0 {
-						lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "[" + DeviceClassList_r.T_remark + "] 中没有找到 至少2条 完整可用数据"})
+					if len(completeDataDeviceClassList) < 2 {
+						lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "[" + DeviceClassList_r.T_remark + "] 中没有找到 至少2条 完整可用数据,【请手动处理!】"})
 						return
 					}
-					SN_List = SN_List_s + SN_List_x
-
-					lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: DeviceClassList_r.T_sn + "|" + DeviceClassList_r.T_id + "开始平均复制到" + SN_List})
-
-					// 开始平均复制到
-					CopySN := DeviceClassList_r.T_sn
-					CopyID := DeviceClassList_r.T_id
-
-					copyTime, _ := lib.TimeStrToTime(CopyTime)
-					endTime, _ := lib.TimeStrToTime(EndTime)
-					startTime, _ := lib.TimeStrToTime(StartTime)
-
-					CopyEndTime := copyTime.Add(endTime.Sub(startTime)).Format("2006-01-02 15:04:05")
-
-					SN_List_Split := strings.Split(strings.Trim(SN_List, "|"), "|")
-					sn_id1 := strings.Split(SN_List_Split[0], ",")
 
-					sn1, id_str1 := sn_id1[0], sn_id1[1]
-					sn_id2 := strings.Split(SN_List_Split[1], ",")
-
-					sn2, id_str2 := sn_id2[0], sn_id2[1]
-					List1, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, sn1, id_str1, StartTime, EndTime, 0, 9999)
-					List2, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, sn2, id_str2, StartTime, EndTime, 0, 9999)
-					num := len(List1)
-					if len(List2) < len(List1) {
-						num = len(List2)
-					}
-					var list []Task.TaskData_
-					ct := copyTime
-					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
-						list = append(list, Task.TaskData_{
-							T_sn:   CopySN,
-							T_id:   CopyID,
-							T_t:    T_t,
-							T_rh:   T_rh,
-							T_time: ct.Format("2006-01-02 15:04:05"),
-						})
-						ct = ct.Add(time.Second * time.Duration(T_saveT))
+					// -----------开始平均复制到
+					device := Device.DeviceClassList{
+						T_id: DeviceClassList_r.T_id,
+						T_sn: DeviceClassList_r.T_sn,
 					}
-					Task.DeleteTaskDataByTimeRange(Task_r.T_task_id, CopySN, CopyID, CopyTime, CopyEndTime)
-					for i, taskData := range list {
-						Task.InsertTaskData(Task_r.T_task_id, taskData)
 
-						if i%100 == 0 {
-							lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: fmt.Sprintf("%d/%d", i, len(list))})
-						}
-					}
+					c.SetAdjacentDeviceAVGTaskData(T_task_id, device, completeDataDeviceClassList, StartTime, EndTime)
+
+					// -----------开始平均复制到结束
 
 				}
 			}
@@ -476,8 +431,9 @@ func CopyFromPositionAverage(c *context.Response, T_task_id string, T_class int,
 	}
 
 	fmt.Println("num:", num)
-	var TaskData_list []Task.TaskData_
 	ct := copyTime
+	var valueStrings []string
+
 	for TaskData_i := 0; TaskData_i < num; TaskData_i++ {
 		if List1[TaskData_i].T_time != List2[TaskData_i].T_time {
 			lib.SseWriteJSON(c, lib.JSONSSE{State: 2, Msg: fmt.Sprintf("%s【%s】、%s【%s】时间不一致", List1[TaskData_i].T_id, List1[TaskData_i].T_time, List2[TaskData_i].T_id, List2[TaskData_i].T_time)})
@@ -485,32 +441,24 @@ func CopyFromPositionAverage(c *context.Response, T_task_id string, T_class int,
 		}
 		T_t := (List1[TaskData_i].T_t + List2[TaskData_i].T_t) / 2
 		T_rh := (List1[TaskData_i].T_rh + List2[TaskData_i].T_rh) / 2
-		TaskData_list = append(TaskData_list, Task.TaskData_{
-			T_sn:   CopySN,
-			T_id:   CopyID,
-			T_t:    T_t,
-			T_rh:   T_rh,
-			T_time: ct.Format("2006-01-02 15:04:05"),
-		})
+		valueStrings = append(valueStrings, fmt.Sprintf("('%s','%s',%v,%v,'%s')", CopySN, CopyID, T_t, T_rh, ct.Format("2006-01-02 15:04:05")))
+
 		ct = ct.Add(time.Second * time.Duration(T_saveT))
 	}
-	fmt.Println("TaskData_list:", len(TaskData_list))
 	Task.DeleteTaskDataByTimeRange(T_task_id, CopySN, CopyID, CopyTime, CopyEndTime)
-	for taskData_i, taskData := range TaskData_list {
-		Task.InsertTaskData(T_task_id, taskData)
 
-		if taskData_i%100 == 0 {
-			lib.SseWriteJSON(c, lib.JSONSSE{State: 0, Msg: fmt.Sprintf("%d/%d", taskData_i, len(TaskData_list))})
-		}
+	err := Task.Batch_Adds_TaskData(T_task_id, valueStrings)
+	if err == nil {
+		lib.SseWriteJSON(c, lib.JSONSSE{State: 0, Msg: fmt.Sprintf("%d/%d", len(valueStrings), len(valueStrings))})
 	}
 
 }
 
-// 绑定点与终端比对  (绑定点数据自检)
+// 绑定点与终端比对  (绑定点数据自检) 终端数据为参照物,绑定点数据在终端偏差±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) //  持续时间
+	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")
@@ -524,135 +472,138 @@ func (c *TaskDataHandleController) SSE_Comparison_between_binding_points_and_ter
 		return
 	}
 
-	// -------------------- 温湿度绑定点1 --------------------
-	温湿度绑定点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
+	// 保温箱偏差为0.5
+	if Task_r.T_device_type == "X" {
+		T_deviation = 0.5
 	}
 
-	监测终端01_list := Device.Read_DeviceClassList_List_id_By_Terminal(Task_r.T_class, true)
-	if len(监测终端01_list) < 1 {
-		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 监测终端!"})
+	// -------------------- 获取开始时间--------------------
+	温度控制范围最高值 := 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
 	}
 
-	结束时间 := 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 {
-		结束时间 = 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: "未找到结束时间 标签!"})
+	// 均匀性布点   产品存放区域测点
+	部点终端_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "均匀性布点")
+	部点终端_list = append(部点终端_list, Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "产品存放区域测点")...)
+	部点终端_list = Device.DeduplicateById(部点终端_list)
+	if len(部点终端_list) <= 2 {
+		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 {
-		开始时间 = 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, "温度分布特性的测试与分析(满载)开始时间")
+	开始时间 := ""
+	// 开始时间 获取温度下降到第二个低点时间
+	// 1. 获取温度平均值
+	部点终端_sn_list := []string{}
+	for _, v := range 部点终端_list {
+		部点终端_sn_list = append(部点终端_sn_list, v.T_sn)
 	}
-	if len(开始时间) == 0 {
-		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到开始时间 标签!"})
+
+	list := Task.Read_TaskData_ById_AVG(Task_r.T_task_id, strings.Join(部点终端_sn_list, "|"), "", "")
+	if len(list) < 2 {
+		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "均匀性布点+产品存放区域测点 数据平均值 少于2条!"})
 		return
 	}
-	温度分布特性的测试与分析_开始时间 := 开始时间
-	温度分布特性的测试与分析_结束时间 := 结束时间
-
-	fmt.Println("温湿度绑定点1   数据准备:", 温湿度绑定点1_list[0].T_id, 监测终端01_list[0].T_id, 温度分布特性的测试与分析_开始时间, 温度分布特性的测试与分析_结束时间)
-
-	var 温湿度绑定点1vga, 监测终端01vga, vgaca float64
-	温湿度绑定点1vga = Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点1_list[0].T_sn, 温湿度绑定点1_list[0].T_id, 温度分布特性的测试与分析_开始时间, 温度分布特性的测试与分析_结束时间)
-	监测终端01vga = Task.Read_TaskData_AVG(T_task_id, 监测终端01_list[0].T_sn, 监测终端01_list[0].T_id, 温度分布特性的测试与分析_开始时间, 温度分布特性的测试与分析_结束时间)
-	vgaca = math.Round((监测终端01vga-温湿度绑定点1vga)*100) / 100.0
-
-	for T_deviation < math.Abs(vgaca) {
-		// 缩放
-		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行缩放 数据!温湿度绑定点1 平均值:" +
-			lib.To_string(温湿度绑定点1vga) + "℃ 监测终端01vga 平均值" + lib.To_string(监测终端01vga) + "℃ 数据偏差: " + lib.To_string(vgaca) + "℃ 设置:" + lib.To_string(T_deviation) + "℃"})
-
-		Task.UpdateTaskDataTemperatureAndHumidityByGeometric_id(T_task_id, 温湿度绑定点1_list[0].T_id, 温度分布特性的测试与分析_开始时间, 温度分布特性的测试与分析_结束时间, 0.95)
-
-		// 偏移
-		温湿度绑定点1vga = Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点1_list[0].T_sn, 温湿度绑定点1_list[0].T_id, 温度分布特性的测试与分析_开始时间, 温度分布特性的测试与分析_结束时间)
-		监测终端01vga = Task.Read_TaskData_AVG(T_task_id, 监测终端01_list[0].T_sn, 监测终端01_list[0].T_id, 温度分布特性的测试与分析_开始时间, 温度分布特性的测试与分析_结束时间)
-		vgaca = math.Round((监测终端01vga-温湿度绑定点1vga)*100) / 100.0
-		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行偏移 数据!温湿度绑定点1 平均值:" +
-			lib.To_string(温湿度绑定点1vga) + "℃ 监测终端01vga 平均值" + lib.To_string(监测终端01vga) + "℃ 数据偏差: " + lib.To_string(vgaca) + "℃ 设置:" + lib.To_string(T_deviation) + "℃"})
-		Task.UpdateTaskDataTemperatureAndHumidityByGeometricAVG(T_task_id, 温湿度绑定点1_list[0].T_id, 温度分布特性的测试与分析_开始时间, 温度分布特性的测试与分析_结束时间, math.Round(((监测终端01vga-温湿度绑定点1vga)*0.8)*100)/100.0)
+	// 找平均值低于温度控制范围最高值的第二个最低点
+	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(温度控制范围最高值) {
+			lowPoint += 1
+		}
 
-		温湿度绑定点1vga = Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点1_list[0].T_sn, 温湿度绑定点1_list[0].T_id, 温度分布特性的测试与分析_开始时间, 温度分布特性的测试与分析_结束时间)
-		监测终端01vga = Task.Read_TaskData_AVG(T_task_id, 监测终端01_list[0].T_sn, 监测终端01_list[0].T_id, 温度分布特性的测试与分析_开始时间, 温度分布特性的测试与分析_结束时间)
-		vgaca = math.Round((监测终端01vga-温湿度绑定点1vga)*100) / 100.0
+		if lowPoint == 2 {
+			开始时间 = list[i].T_time
+			break
+		}
 
 	}
 
-	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "数据满足要求!温湿度绑定点1 平均值:" + lib.To_string(温湿度绑定点1vga) + "℃ 监测终端01vga 平均值" + lib.To_string(监测终端01vga) + "℃ 数据偏差: " + lib.To_string(vgaca) + "℃ !"})
-
-	// -------------------- 温湿度绑定点2 --------------------
-
-	温湿度绑定点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 没找到,跳过 温湿度绑定点2"})
-		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "完成!"})
-		return
-	}
-	监测终端02_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "监测终端02")
-	if len(监测终端02_list) != 1 {
-		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "监测终端02 中找到 " + lib.To_string(len(监测终端02_list)) + "条,布点终端异常!"})
+	if len(开始时间) == 0 {
+		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 开始时间 数据!"})
 		return
 	}
+	// -------------------- 获取开始时间结束 --------------------
 
-	fmt.Println("温湿度绑定点2  数据准备:", 温湿度绑定点2_list[0].T_id, 监测终端02_list[0].T_id, 温度分布特性的测试与分析_开始时间, 温度分布特性的测试与分析_结束时间)
-
-	var 温湿度绑定点2vga, 监测终端02vga float64
-	温湿度绑定点2vga = Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点2_list[0].T_sn, 温湿度绑定点2_list[0].T_id, 温度分布特性的测试与分析_开始时间, 温度分布特性的测试与分析_结束时间)
-	监测终端02vga = Task.Read_TaskData_AVG(T_task_id, 监测终端02_list[0].T_sn, 监测终端02_list[0].T_id, 温度分布特性的测试与分析_开始时间, 温度分布特性的测试与分析_结束时间)
-	vgaca = math.Round((监测终端02vga-温湿度绑定点2vga)*100) / 100.0
+	结束时间 := 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 {
+		结束时间 = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "现场测试结束时间")
+	}
 
-	for T_deviation < math.Abs(vgaca) {
-		// 缩放
-		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行缩放 数据!温湿度绑定点2 平均值:" +
-			lib.To_string(温湿度绑定点2vga) + "℃ 监测终端02vga 平均值" + lib.To_string(监测终端02vga) + "℃ 数据偏差: " + lib.To_string(vgaca) + "℃ 设置:" + lib.To_string(T_deviation) + "℃"})
+	if len(结束时间) == 0 {
+		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到结束时间 标签!"})
+		return
+	}
 
-		Task.UpdateTaskDataTemperatureAndHumidityByGeometric_id(T_task_id, 温湿度绑定点2_list[0].T_id, 温度分布特性的测试与分析_开始时间, 温度分布特性的测试与分析_结束时间, 0.95)
+	监测终端_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: "未找到 监测终端!"})
+	}
+	// 查询监测终端开始时间
 
-		// 偏移
-		温湿度绑定点2vga = Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点2_list[0].T_sn, 温湿度绑定点2_list[0].T_id, 温度分布特性的测试与分析_开始时间, 温度分布特性的测试与分析_结束时间)
-		监测终端02vga = Task.Read_TaskData_AVG(T_task_id, 监测终端02_list[0].T_sn, 监测终端02_list[0].T_id, 温度分布特性的测试与分析_开始时间, 温度分布特性的测试与分析_结束时间)
-		vgaca = math.Round((监测终端02vga-温湿度绑定点2vga)*100) / 100.0
-		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行偏移 数据!温湿度绑定点2 平均值:" +
-			lib.To_string(温湿度绑定点2vga) + "℃ 监测终端02vga 平均值" + lib.To_string(监测终端02vga) + "℃ 数据偏差: " + lib.To_string(vgaca) + "℃ 设置:" + lib.To_string(T_deviation) + "℃"})
-		Task.UpdateTaskDataTemperatureAndHumidityByGeometricAVG(T_task_id, 温湿度绑定点2_list[0].T_id, 温度分布特性的测试与分析_开始时间, 温度分布特性的测试与分析_结束时间, math.Round(((监测终端02vga-温湿度绑定点2vga)*0.8)*100)/100.0)
+	for i, 监测终端 := range 监测终端_list {
 
-		温湿度绑定点2vga = Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点2_list[0].T_sn, 温湿度绑定点2_list[0].T_id, 温度分布特性的测试与分析_开始时间, 温度分布特性的测试与分析_结束时间)
-		监测终端02vga = Task.Read_TaskData_AVG(T_task_id, 监测终端02_list[0].T_sn, 监测终端02_list[0].T_id, 温度分布特性的测试与分析_开始时间, 温度分布特性的测试与分析_结束时间)
-		vgaca = math.Round((监测终端02vga-温湿度绑定点2vga)*100) / 100.0
+		// -------------------- 温湿度绑定点 --------------------
+		温湿度绑定点_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "温湿度绑定点"+lib.To_string(i+1))
+		if len(温湿度绑定点_list) != 1 {
+			lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温湿度绑定点" + lib.To_string(i+1) + " 中找到 " + lib.To_string(len(温湿度绑定点_list)) + "条,只允许 一条数据!"})
+		}
 
+		fmt.Println("温湿度绑定点"+lib.To_string(i+1)+"数据准备:", 温湿度绑定点_list[0].T_id, 监测终端.T_id, 开始时间, 结束时间)
+
+		var 温湿度绑定点vga, 监测终端vga, vgaca float64
+		温湿度绑定点vga = Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点_list[0].T_sn, 温湿度绑定点_list[0].T_id, 开始时间, 结束时间)
+		监测终端vga = Task.Read_TaskData_AVG(T_task_id, 监测终端.T_sn, 监测终端.T_id, 开始时间, 结束时间)
+		vgaca = RoundToDecimal(监测终端vga-温湿度绑定点vga, 1)
+
+		for T_deviation < math.Abs(vgaca) {
+			// 缩放
+			lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行缩放 数据!" +
+				"温湿度绑定点" + lib.To_string(i+1) + " 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " +
+				"监测终端0" + lib.To_string(i+1) + " 平均值" + lib.To_string(监测终端vga) + "℃ " +
+				"数据偏差: " + lib.To_string(vgaca) + "℃ " +
+				"设置:" + lib.To_string(T_deviation) + "℃"})
+			// 获取缩放度
+			compress := RoundToDecimal((监测终端vga-T_deviation-0.1)/温湿度绑定点vga, 2)
+			// 缩放
+			Task.UpdateTaskDataTemperatureAndHumidityByGeometric_id(T_task_id, 温湿度绑定点_list[0].T_id, "", "", compress)
+
+			// 偏移
+			温湿度绑定点vga = Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点_list[0].T_sn, 温湿度绑定点_list[0].T_id, 开始时间, 结束时间)
+			监测终端vga = Task.Read_TaskData_AVG(T_task_id, 监测终端.T_sn, 监测终端.T_id, 开始时间, 结束时间)
+			vgaca = math.Round((监测终端vga-温湿度绑定点vga)*100) / 100.0
+			lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行偏移 数据!" +
+				"温湿度绑定点1 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " +
+				"监测终端0" + lib.To_string(i+1) + " 平均值" + lib.To_string(监测终端vga) + "℃ " +
+				"数据偏差: " + lib.To_string(vgaca) + "℃ " +
+				"设置:" + lib.To_string(T_deviation) + "℃"})
+			Task.UpdateTaskDataTemperatureAndHumidityByGeometricAVG(T_task_id, 温湿度绑定点_list[0].T_id, "", "", math.Round(((监测终端vga-温湿度绑定点vga)*0.8)*100)/100.0)
+
+			温湿度绑定点vga = Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点_list[0].T_sn, 温湿度绑定点_list[0].T_id, 开始时间, 结束时间)
+			监测终端vga = Task.Read_TaskData_AVG(T_task_id, 监测终端.T_sn, 监测终端.T_id, 开始时间, 结束时间)
+			vgaca = RoundToDecimal(监测终端vga-温湿度绑定点vga, 1)
+		}
+		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "数据满足要求!" +
+			"温湿度绑定点" + lib.To_string(i+1) + " 平均值:" + lib.To_string(温湿度绑定点vga) + "℃ " +
+			"监测终端0" + lib.To_string(i+1) + " 平均值" + lib.To_string(监测终端vga) + "℃ " +
+			"数据偏差: " + lib.To_string(vgaca) + "℃ !"})
 	}
-	//
-	//lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "数据满足要求!温湿度绑定点2 平均值:" + lib.To_string(温湿度绑定点2vga) + "℃ 监测终端02vga 平均值" + lib.To_string(监测终端02vga) + "℃ 数据偏差: " + lib.To_string(vgaca) + "℃ !"})
+
 	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) //  持续时间
+	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")
@@ -665,57 +616,51 @@ func (c *TaskDataHandleController) SSE_Compare_binding_points_with_cold_and_hot_
 		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
+	}
 
 	// 均匀性布点   产品存放区域测点
 	部点终端_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "均匀性布点")
 	部点终端_list = append(部点终端_list, Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "产品存放区域测点")...)
-
-	//开始时间 := 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 {
-	//	开始时间 = 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
-	//}
+	部点终端_list = Device.DeduplicateById(部点终端_list)
 	开始时间 := ""
-	if Task_r.T_device_type == "C" {
-		// 任务类型为C的时候,获取温度下降到最低点时间
-		// 1. 获取温度平均值
-		部点终端_sn_list := []string{}
-		for _, v := range 部点终端_list {
-			部点终端_sn_list = append(部点终端_sn_list, v.T_sn)
-		}
-		list := Task.Read_TaskData_ById_AVG(Task_r.T_task_id, strings.Join(部点终端_sn_list, "|"), "", "")
-		if len(list) < 2 {
-			lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "均匀性布点+产品存放区域测点 数据平均值 少于2条!"})
-			return
-		}
-		// 查找最低点
-		// 找最低点
-		minRecord := list[0]
-		for i := 1; i <= len(list); i++ {
-			if list[i].T_t < minRecord.T_t {
-				minRecord = list[i]
-			}
-			if list[i].T_t > list[i-1].T_t {
-				break
-			}
+	// 开始时间 获取温度下降到第二个低点时间
+	// 1. 获取温度平均值
+	部点终端_sn_list := []string{}
+	for _, v := range 部点终端_list {
+		部点终端_sn_list = append(部点终端_sn_list, v.T_sn)
+	}
+
+	list := Task.Read_TaskData_ById_AVG(Task_r.T_task_id, strings.Join(部点终端_sn_list, "|"), "", "")
+	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(温度控制范围最高值) {
+			lowPoint += 1
 		}
-		开始时间 = minRecord.T_time
-	} else {
-		现场测试开始时间 := VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "现场测试开始时间")
-		if len(现场测试开始时间) == 0 || 现场测试开始时间 == "null" {
-			lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 现场测试开始时间 失败!"})
-			return
+
+		if lowPoint == 2 {
+			开始时间 = list[i].T_time
+			break
 		}
-		开始时间 = 现场测试开始时间
+
+	}
+
+	if len(开始时间) == 0 {
+		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 开始时间 数据!"})
+		return
 	}
 
 	// ------------------
@@ -724,17 +669,15 @@ func (c *TaskDataHandleController) SSE_Compare_binding_points_with_cold_and_hot_
 		结束时间 = 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 {
-		结束时间 = VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "温度分布特性的测试与分析(空载)结束时间")
+		结束时间 = 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
 	}
 
-	温度分布特性的测试与分析_结束时间 := 结束时间
+	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "--- 开始时间---  " + 开始时间})
+	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "--- 结束时间---  " + 结束时间})
 
 	if len(部点终端_list) <= 2 {
 		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "均匀性布点,产品存放区域测点 太少了,至少两条以上!"})
@@ -746,7 +689,7 @@ func (c *TaskDataHandleController) SSE_Compare_binding_points_with_cold_and_hot_
 	}
 	var AVGClassList_r []AVGClassList
 	for _, i2 := range 部点终端_list {
-		AVGClassList_r = append(AVGClassList_r, AVGClassList{T_id: i2.T_id, T_vga: Task.Read_TaskData_AVG(T_task_id, i2.T_sn, i2.T_id, 开始时间, 温度分布特性的测试与分析_结束时间)})
+		AVGClassList_r = append(AVGClassList_r, AVGClassList{T_id: i2.T_id, T_vga: Task.Read_TaskData_AVG(T_task_id, i2.T_sn, i2.T_id, 开始时间, 结束时间)})
 	}
 	// 使用 sort.Slice 对切片进行排序
 	sort.Slice(AVGClassList_r, func(i, j int) bool {
@@ -768,8 +711,8 @@ func (c *TaskDataHandleController) SSE_Compare_binding_points_with_cold_and_hot_
 		温湿度绑定点2_list = 温湿度绑定点1_list
 		温湿度绑定点2_list_is = false
 	}
-	温湿度绑定点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, 开始时间, 温度分布特性的测试与分析_结束时间)
+	温湿度绑定点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 平均值相等,将 进行上下偏移处理!"})
@@ -802,16 +745,20 @@ func (c *TaskDataHandleController) SSE_Compare_binding_points_with_cold_and_hot_
 
 	for T_deviation < math.Abs(vgaca) {
 		// 缩放
-		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行缩放 数据!热点" + lib.To_string(AVGClassList_r[0].T_id) + " 平均值:" + lib.To_string(AVGClassList_r[0].T_vga) +
-			"℃ 高点 " + lib.To_string(温湿度绑定点vga_H.T_id) + " 平均值" + lib.To_string(温湿度绑定点vga_H.T_vga) + "℃ 数据偏差: " + lib.To_string(vgaca) + "℃ 设置:" + lib.To_string(T_deviation) + "℃"})
+		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行缩放 数据!热点" + lib.To_string(AVGClassList_r[0].T_id) +
+			" 平均值:" + lib.To_string(AVGClassList_r[0].T_vga) + "℃ " +
+			"高点 " + lib.To_string(温湿度绑定点vga_H.T_id) +
+			" 平均值" + lib.To_string(fmt.Sprintf("%.2f", 温湿度绑定点vga_H.T_vga)) + "℃ " +
+			"数据偏差: " + lib.To_string(vgaca) + "℃ " +
+			"设置:" + lib.To_string(T_deviation) + "℃"})
 
-		Task.UpdateTaskDataTemperatureAndHumidityByGeometric_id(T_task_id, AVGClassList_r[0].T_id, 开始时间, 温度分布特性的测试与分析_结束时间, 0.95)
+		Task.UpdateTaskDataTemperatureAndHumidityByGeometric_id(T_task_id, AVGClassList_r[0].T_id, "", "", 0.95)
 
 		// 偏移
 		// 均匀性布点   产品存放区域测点
 		AVGClassList_r = AVGClassList_r[:0] // 清空切片
 		for _, i2 := range 部点终端_list {
-			AVGClassList_r = append(AVGClassList_r, AVGClassList{T_id: i2.T_id, T_vga: Task.Read_TaskData_AVG(T_task_id, i2.T_sn, i2.T_id, 开始时间, 温度分布特性的测试与分析_结束时间)})
+			AVGClassList_r = append(AVGClassList_r, AVGClassList{T_id: i2.T_id, T_vga: Task.Read_TaskData_AVG(T_task_id, i2.T_sn, i2.T_id, 开始时间, 结束时间)})
 		}
 		// 使用 sort.Slice 对切片进行排序
 		sort.Slice(AVGClassList_r, func(i, j int) bool {
@@ -824,12 +771,12 @@ func (c *TaskDataHandleController) SSE_Compare_binding_points_with_cold_and_hot_
 		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行偏移 数据!热点" + lib.To_string(AVGClassList_r[0].T_id) + " 平均值:" + lib.To_string(AVGClassList_r[0].T_vga) +
 			"℃ 高点 " + lib.To_string(温湿度绑定点vga_H.T_id) + " 平均值" + lib.To_string(温湿度绑定点vga_H.T_vga) + "℃ 数据偏差: " + lib.To_string(vgaca) + "℃ 设置:" + lib.To_string(T_deviation) + "℃"})
 
-		Task.UpdateTaskDataTemperatureAndHumidityByGeometricAVG(T_task_id, AVGClassList_r[0].T_id, 开始时间, 温度分布特性的测试与分析_结束时间, math.Round(((vgaca)*0.8)*100)/100.0)
+		Task.UpdateTaskDataTemperatureAndHumidityByGeometricAVG(T_task_id, AVGClassList_r[0].T_id, "", "", math.Round(((vgaca)*0.8)*100)/100.0)
 
 		// 均匀性布点   产品存放区域测点
 		AVGClassList_r = AVGClassList_r[:0] // 清空切片
 		for _, i2 := range 部点终端_list {
-			AVGClassList_r = append(AVGClassList_r, AVGClassList{T_id: i2.T_id, T_vga: Task.Read_TaskData_AVG(T_task_id, i2.T_sn, i2.T_id, 开始时间, 温度分布特性的测试与分析_结束时间)})
+			AVGClassList_r = append(AVGClassList_r, AVGClassList{T_id: i2.T_id, T_vga: Task.Read_TaskData_AVG(T_task_id, i2.T_sn, i2.T_id, 开始时间, 结束时间)})
 		}
 		// 使用 sort.Slice 对切片进行排序
 		sort.Slice(AVGClassList_r, func(i, j int) bool {
@@ -840,8 +787,12 @@ func (c *TaskDataHandleController) SSE_Compare_binding_points_with_cold_and_hot_
 		vgaca = math.Round((温湿度绑定点vga_H.T_vga-AVGClassList_r[0].T_vga)*100) / 100.0
 
 	}
-	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "热点 数据满足要求!热点" + lib.To_string(AVGClassList_r[0].T_id) + " 平均值:" + lib.To_string(AVGClassList_r[0].T_vga) +
-		"℃ 高点 " + lib.To_string(温湿度绑定点vga_H.T_id) + " 平均值" + lib.To_string(温湿度绑定点vga_H.T_vga) + "℃ 数据偏差: " + lib.To_string(vgaca) + "℃ "})
+	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "热点 数据满足要求!" +
+		"热点" + lib.To_string(AVGClassList_r[0].T_id) +
+		" 平均值:" + lib.To_string(AVGClassList_r[0].T_vga) + "℃ " +
+		"高点 " + lib.To_string(温湿度绑定点vga_H.T_id) +
+		" 平均值" + lib.To_string(fmt.Sprintf("%.2f", 温湿度绑定点vga_H.T_vga)) + "℃ " +
+		"数据偏差: " + lib.To_string(vgaca) + "℃ "})
 
 	// -------------------- 温湿度绑定点vga_L --------------------
 	if !温湿度绑定点2_list_is {
@@ -855,16 +806,21 @@ func (c *TaskDataHandleController) SSE_Compare_binding_points_with_cold_and_hot_
 	vgaca = math.Round((温湿度绑定点vga_L.T_vga-AVGClassList_r[len(AVGClassList_r)-1].T_vga)*100) / 100.0
 	for T_deviation < math.Abs(vgaca) {
 		// 缩放
-		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行缩放 数据!冷点" + lib.To_string(AVGClassList_r[len(AVGClassList_r)-1].T_id) + " 平均值:" + lib.To_string(AVGClassList_r[len(AVGClassList_r)-1].T_vga) +
-			"℃ 低点 " + lib.To_string(温湿度绑定点vga_L.T_id) + " 平均值" + lib.To_string(温湿度绑定点vga_L.T_vga) + "℃ 数据偏差: " + lib.To_string(vgaca) + "℃ 设置:" + lib.To_string(T_deviation) + "℃"})
+		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行缩放 数据!" +
+			"冷点" + lib.To_string(AVGClassList_r[len(AVGClassList_r)-1].T_id) +
+			" 平均值:" + lib.To_string(AVGClassList_r[len(AVGClassList_r)-1].T_vga) + "℃ " +
+			"低点 " + lib.To_string(温湿度绑定点vga_L.T_id) +
+			" 平均值" + lib.To_string(温湿度绑定点vga_L.T_vga) + "℃ " +
+			"数据偏差: " + lib.To_string(vgaca) + "℃ " +
+			"设置:" + lib.To_string(T_deviation) + "℃"})
 
-		Task.UpdateTaskDataTemperatureAndHumidityByGeometric_id(T_task_id, AVGClassList_r[len(AVGClassList_r)-1].T_id, 开始时间, 温度分布特性的测试与分析_结束时间, 0.95)
+		Task.UpdateTaskDataTemperatureAndHumidityByGeometric_id(T_task_id, AVGClassList_r[len(AVGClassList_r)-1].T_id, "", "", 0.95)
 
 		// 偏移
 		// 均匀性布点   产品存放区域测点
 		AVGClassList_r = AVGClassList_r[:0] // 清空切片
 		for _, i2 := range 部点终端_list {
-			AVGClassList_r = append(AVGClassList_r, AVGClassList{T_id: i2.T_id, T_vga: Task.Read_TaskData_AVG(T_task_id, i2.T_sn, i2.T_id, 开始时间, 温度分布特性的测试与分析_结束时间)})
+			AVGClassList_r = append(AVGClassList_r, AVGClassList{T_id: i2.T_id, T_vga: Task.Read_TaskData_AVG(T_task_id, i2.T_sn, i2.T_id, 开始时间, 结束时间)})
 		}
 		// 使用 sort.Slice 对切片进行排序
 		sort.Slice(AVGClassList_r, func(i, j int) bool {
@@ -877,12 +833,12 @@ func (c *TaskDataHandleController) SSE_Compare_binding_points_with_cold_and_hot_
 		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行偏移 数据!冷点" + lib.To_string(AVGClassList_r[len(AVGClassList_r)-1].T_id) + " 平均值:" + lib.To_string(AVGClassList_r[len(AVGClassList_r)-1].T_vga) +
 			"℃ 低点 " + lib.To_string(温湿度绑定点vga_L.T_id) + " 平均值" + lib.To_string(温湿度绑定点vga_L.T_vga) + "℃ 数据偏差: " + lib.To_string(vgaca) + "℃ 设置:" + lib.To_string(T_deviation) + "℃"})
 
-		Task.UpdateTaskDataTemperatureAndHumidityByGeometricAVG(T_task_id, AVGClassList_r[len(AVGClassList_r)-1].T_id, 开始时间, 温度分布特性的测试与分析_结束时间, math.Round(((vgaca)*0.8)*100)/100.0)
+		Task.UpdateTaskDataTemperatureAndHumidityByGeometricAVG(T_task_id, AVGClassList_r[len(AVGClassList_r)-1].T_id, "", "", math.Round(((vgaca)*0.8)*100)/100.0)
 
 		// 均匀性布点   产品存放区域测点
 		AVGClassList_r = AVGClassList_r[:0] // 清空切片
 		for _, i2 := range 部点终端_list {
-			AVGClassList_r = append(AVGClassList_r, AVGClassList{T_id: i2.T_id, T_vga: Task.Read_TaskData_AVG(T_task_id, i2.T_sn, i2.T_id, 开始时间, 温度分布特性的测试与分析_结束时间)})
+			AVGClassList_r = append(AVGClassList_r, AVGClassList{T_id: i2.T_id, T_vga: Task.Read_TaskData_AVG(T_task_id, i2.T_sn, i2.T_id, 开始时间, 结束时间)})
 		}
 		// 使用 sort.Slice 对切片进行排序
 		sort.Slice(AVGClassList_r, func(i, j int) bool {
@@ -901,7 +857,7 @@ func (c *TaskDataHandleController) SSE_Compare_binding_points_with_cold_and_hot_
 	c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
 }
 
-// 区间数据校正  (布点区域数据自检)
+// 区间数据校正  (布点区域数据自检) 均匀性布点,产品存放区域测点 区间数据超标校正 超标数据偏移到区间内
 func (c *TaskDataHandleController) SSE_Interval_data_correction() {
 
 	T_task_id := c.GetString("T_task_id") //  v26nplogbwt1
@@ -918,17 +874,12 @@ func (c *TaskDataHandleController) SSE_Interval_data_correction() {
 		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 {
-		结束时间 = 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, "温度分布特性的测试与分析(空载)结束时间")
+		结束时间 = 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: "未找到结束时间 标签!"})
@@ -940,142 +891,241 @@ func (c *TaskDataHandleController) SSE_Interval_data_correction() {
 		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温度控制范围 标签值不正确!"})
 		return
 	}
+
 	// 均匀性布点   产品存放区域测点
 	部点终端_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "均匀性布点")
 	部点终端_list = append(部点终端_list, Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "产品存放区域测点")...)
+	部点终端_list = Device.DeduplicateById(部点终端_list)
 	if len(部点终端_list) <= 2 {
 		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "均匀性布点,产品存放区域测点 太少了,至少两条以上!"})
 		return
 	}
 
-	//List_data, _ := Task.Read_TaskData_ById_List(Task_r.T_task_id, 部点终端_list[0].T_sn, 部点终端_list[0].T_id, "", "", 0, 9999)
-	//开始时间 := List_data[len(List_data) - 1].T_time
-
-	//开始时间 := 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 Task_r.T_device_type == "C" {
-		// 任务类型为C的时候,获取温度下降到最低点时间
-		// 1. 获取温度平均值
-		部点终端_sn_list := []string{}
-		for _, v := range 部点终端_list {
-			部点终端_sn_list = append(部点终端_sn_list, v.T_sn)
-		}
-		list := Task.Read_TaskData_ById_AVG(Task_r.T_task_id, strings.Join(部点终端_sn_list, "|"), "", "")
-		if len(list) < 2 {
-			lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "均匀性布点+产品存放区域测点 数据平均值 少于2条!"})
-			return
-		}
-		// 查找最低点
-		// 找最低点
-		minRecord := list[0]
-		for i := 1; i <= len(list); i++ {
-			if list[i].T_t < minRecord.T_t {
-				minRecord = list[i]
-			}
-			if list[i].T_t > list[i-1].T_t {
-				break
-			}
+	// 开始时间 获取温度下降到第二个低点时间
+	// 1. 获取温度平均值
+	部点终端_sn_list := []string{}
+	for _, v := range 部点终端_list {
+		部点终端_sn_list = append(部点终端_sn_list, v.T_sn)
+	}
+
+	list := Task.Read_TaskData_ById_AVG(Task_r.T_task_id, strings.Join(部点终端_sn_list, "|"), "", "")
+	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(温度控制范围最高值) {
+			lowPoint += 1
 		}
-		开始时间 = minRecord.T_time
-	} else {
-		现场测试开始时间 := VerifyTemplate.Read_VerifyTemplateMapData_T_name(Task_r.T_task_id, Task_r.T_VerifyTemplate_id, "现场测试开始时间")
-		if len(现场测试开始时间) == 0 || 现场测试开始时间 == "null" {
-			lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 现场测试开始时间 失败!"})
-			return
+
+		if lowPoint == 2 {
+			开始时间 = list[i].T_time
+			break
 		}
-		开始时间 = 现场测试开始时间
+
 	}
+
 	if len(开始时间) == 0 {
-		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到开始时间 标签!"})
+		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "未找到 开始时间 数据!"})
 		return
 	}
 
 	type AVGClassList struct {
-		T_id  string
-		T_max float64
-		T_min float64
+		T_sn   string
+		T_id   string
+		T_max  float64
+		T_min  float64
+		T_diff float64 // 最大最小值差异
 	}
 	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_id: i2.T_id, T_max: T_max, T_min: T_min})
+		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})
 	}
 	fmt.Println("AVGClassList_r:", AVGClassList_r)
 
 	fmt.Println("数据准备:", 开始时间, 结束时间, 温度控制范围最小值, 温度控制范围最高值)
 
-	// -------  温湿度绑定点
-	AVGClassList_is := true
-
 	// -------------------- 温湿度绑定点vga_H --------------------
 	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "--- 进行处理 数据!---"})
-	for AVGClassList_is {
-		AVGClassList_is = false
-		// 准备数据
-		AVGClassList_r = AVGClassList_r[:0]
-		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_id: i2.T_id, T_max: T_max, T_min: T_min})
+	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: fmt.Sprintf("开始时间:%s 结束时间:%s", 开始时间, 结束时间)})
+
+	for _, AVGClassList_i := range AVGClassList_r {
+		var vgaca float64
+		if AVGClassList_i.T_max > 温度控制范围最高值 && AVGClassList_i.T_min < 温度控制范围最小值 {
+
+			// 压缩
+			diff := RoundToDecimal(AVGClassList_i.T_max-AVGClassList_i.T_min, 1)
+			// 获取压缩度
+			compress := RoundToDecimal((温度控制范围最高值-温度控制范围最小值-0.4)/diff, 2)
+			// 压缩
+			Task.UpdateTaskDataTemperatureAndHumidityByGeometric(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", compress, 1)
+			// 向上偏移
+			vgaca = RoundToDecimal(温度控制范围最小值-AVGClassList_i.T_min*compress, 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(compress) +
+				" 向上偏移:" + lib.To_string(RoundToDecimal(vgaca+0.1, 1)) + "℃ "})
+
+			Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", RoundToDecimal(vgaca+0.1, 1), 0)
 		}
-
-		for _, AVGClassList_i := range AVGClassList_r {
-			var vgaca float64
-			if AVGClassList_i.T_max > 温度控制范围最高值 {
-				AVGClassList_is = true
-
-				vgaca = math.Round((温度控制范围最高值-AVGClassList_i.T_max)*100) / 100.0
-				// 缩放
-				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(vgaca) + "℃ 设置高:" + lib.To_string(温度控制范围最高值) + "℃"})
-				Task.UpdateTaskDataTemperatureAndHumidityByGeometric_id(T_task_id, AVGClassList_i.T_id, 开始时间, 结束时间, 0.95)
-				Task.UpdateTaskDataTemperatureAndHumidityByGeometricAVG(T_task_id, AVGClassList_r[0].T_id, 开始时间, 结束时间, math.Round(((vgaca)*0.8)*100)/100.0)
-
+		if (AVGClassList_i.T_max - AVGClassList_i.T_min) > (温度控制范围最高值 - 温度控制范围最小值 - 0.2) {
+
+			// 压缩
+			diff := RoundToDecimal(AVGClassList_i.T_max-AVGClassList_i.T_min, 1)
+			// 获取压缩度
+			compress := RoundToDecimal((温度控制范围最高值-温度控制范围最小值-0.4)/diff, 2)
+			// 压缩
+			Task.UpdateTaskDataTemperatureAndHumidityByGeometric(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", compress, 1)
+
+			// 判断压缩后是否在 温度控制范围最小值-温度控制范围最高值范围内 不做处理
+			if AVGClassList_i.T_max*compress > 温度控制范围最高值 && AVGClassList_i.T_min*compress < 温度控制范围最小值 {
+				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(fmt.Sprintf("%.2f", compress)) +
+					" 压缩后最大值:" + lib.To_string(fmt.Sprintf("%.2f", AVGClassList_i.T_max*compress)) + "℃  " +
+					" 压缩后最小值:" + lib.To_string(fmt.Sprintf("%.2f", AVGClassList_i.T_min*compress)) + "℃  "})
+				continue
 			}
-			if AVGClassList_i.T_min < 温度控制范围最小值 {
-				AVGClassList_is = true
-
-				vgaca = math.Round((温度控制范围最小值-AVGClassList_i.T_min)*100) / 100.0
-				// 缩放
-				lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + lib.To_string(AVGClassList_i.T_id) + " 最小值:" + lib.To_string(AVGClassList_i.T_min) +
-					"℃  " + " 数据偏差: " + lib.To_string(vgaca) + "℃ 设置小:" + lib.To_string(温度控制范围最小值) + "℃"})
-				Task.UpdateTaskDataTemperatureAndHumidityByGeometric_id(T_task_id, AVGClassList_i.T_id, 开始时间, 结束时间, 0.95)
-				vgaca += float64(AVGClassList_i.T_min) - (AVGClassList_i.T_min * 0.95)
-
-				Task.UpdateTaskDataTemperatureAndHumidityByGeometricAVG(T_task_id, AVGClassList_i.T_id, 开始时间, 结束时间, math.Round(((vgaca)*1.2)*100)/100.0)
+			// 压缩后仍高于 温度控制范围最高值,向下偏移
+			if AVGClassList_i.T_max*compress > 温度控制范围最高值 {
+				vgaca = RoundToDecimal(AVGClassList_i.T_max*compress-温度控制范围最高值, 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(AVGClassList_i.T_max*compress) + "℃  " +
+					" 压缩后最小值:" + lib.To_string(AVGClassList_i.T_min*compress) + "℃  " +
+					" 数据偏差:" + lib.To_string(vgaca) + "℃ " +
+					" 向下偏移:" + lib.To_string(RoundToDecimal(vgaca+0.1, 1)) + "℃ "})
+
+				Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", -RoundToDecimal(vgaca+0.1, 1), 0)
+				continue
+			}
+			// 压缩后仍低于 温度控制范围最小值,向上偏移
+			if AVGClassList_i.T_min*compress < 温度控制范围最小值 {
+				// 向上偏移
+				vgaca = RoundToDecimal(温度控制范围最小值-AVGClassList_i.T_min*compress, 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(AVGClassList_i.T_max*compress) + "℃  " +
+					" 压缩后最小值:" + lib.To_string(AVGClassList_i.T_min*compress) + "℃  " +
+					" 数据偏差:" + lib.To_string(vgaca) + "℃ " +
+					" 向上偏移:" + lib.To_string(RoundToDecimal(vgaca+0.1, 1)) + "℃ "})
+
+				Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", RoundToDecimal(vgaca+0.1, 1), 0)
 
 			}
+			continue
+		}
+		// 向下偏移
+		if AVGClassList_i.T_max > 温度控制范围最高值 {
+			vgaca = RoundToDecimal(AVGClassList_i.T_max-温度控制范围最高值, 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(RoundToDecimal(vgaca+0.1, 1)) + "℃ "})
+			// 偏移
+			Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", -RoundToDecimal(vgaca+0.1, 1), 0)
+			continue
 		}
-		if AVGClassList_is {
-			lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "------ 还有 数据需要修改 ------"})
+		if AVGClassList_i.T_min < 温度控制范围最小值 {
+			vgaca = RoundToDecimal(温度控制范围最小值-AVGClassList_i.T_min, 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(RoundToDecimal(vgaca+0.1, 1)) + "℃ "})
+			Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", RoundToDecimal(vgaca+0.1, 1), 0)
 		}
 
 	}
+
 	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "完成!"})
 
 	// Close the connection
 	c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
 }
 
-// 数据等比咧缩放      温度 湿度比列
-//func DataGeometricScale(T_task_id,SN_List_s,StartTime,EndTime string,Temperature,Humidity float64) {
-//
-//	SN_List := strings.Split(strings.Trim(SN_List_s, "|"), "|")
-//
-//	for _, v := range SN_List {
-//		sn_id := strings.Split(v, ",")
-//		if len(sn_id) != 2 {
-//			continue
-//		}
-//		sn, id := sn_id[0], sn_id[1]
-//
-//
-//
-//	}
-//
-//	return
-//}
+// 获取相邻2个终端值平均复制到
+func (c *TaskDataHandleController) SetAdjacentDeviceAVGTaskData(T_task_id string, device Device.DeviceClassList, data []Device.DeviceClassList, StartTime, EndTime string) {
+
+	twoDevice := getBeforeAndAfter(device.T_id, data)
+	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 {
+			c.Data["json"] = lib.JSONS{202, fmt.Sprintf("%s【%s】、%s【%s】时间不一致", List1[i].T_id, List1[i].T_time, List2[i].T_id, List2[i].T_time), nil}
+			c.ServeJSON()
+			return
+			//ct = ct.Add(time.Second * time.Duration(T_saveT))
+			//continue
+		}
+		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
+}

+ 17 - 2
models/Device/DeviceClassList.go

@@ -310,8 +310,8 @@ func Read_DeviceClassList_List_id_By_Terminal(T_class_Id int, T_Terminal bool) (
 		qs.Filter("T_class", T_class_Id).Filter("T_State", 1).Filter("T_terminal", 2).All(&r)
 		return r
 	}
-	// T_terminal = 1 测点
-	qs.Filter("T_class", T_class_Id).Filter("T_State", 1).Filter("T_terminal", 1).All(&r)
+	// T_terminal = 1,0 测点
+	qs.Filter("T_class", T_class_Id).Filter("T_State", 1).Filter("T_terminal__lt", 2).All(&r)
 	return r
 }
 
@@ -378,3 +378,18 @@ func Del_DeviceClassList_Duplication(T_class int) error {
 	logs.Debug("删除重复设备列表: ", num)
 	return nil
 }
+
+func DeduplicateById(devices []DeviceClassList) []DeviceClassList {
+	unique := make(map[int]DeviceClassList)
+	for _, device := range devices {
+		if _, exists := unique[device.Id]; !exists {
+			unique[device.Id] = device
+		}
+	}
+
+	result := make([]DeviceClassList, 0, len(unique))
+	for _, device := range unique {
+		result = append(result, device)
+	}
+	return result
+}

+ 90 - 26
models/Task/TaskData.go

@@ -626,6 +626,39 @@ func Adds_TaskData(T_task_id string, valueStrings []string) error {
 	return nil
 }
 
+// 批量添加数据
+func Batch_Adds_TaskData(T_task_id string, valueStrings []string) error {
+
+	pageSize := 10000                          // 每页的条数
+	totalPages := len(valueStrings) / pageSize // 总页数
+
+	// 遍历每一页
+	for page := 1; page <= totalPages+1; page++ {
+
+		// 计算当前页的起始索引和结束索引
+		startIndex := (page - 1) * pageSize
+		if startIndex > len(valueStrings) {
+			startIndex = len(valueStrings)
+		}
+		endIndex := page * pageSize
+
+		// 边界判断,如果结束索引超过列表长度,则将结束索引设置为列表最后一个元素的索引加一
+		if endIndex > len(valueStrings) {
+			endIndex = len(valueStrings)
+		}
+
+		// 获取当前页的数据
+		currentList := valueStrings[startIndex:endIndex]
+		err := Adds_TaskData(T_task_id, currentList)
+		if err != nil {
+			return err
+		}
+		logs.Info(fmt.Sprintf("第%d-%d条数据插入成功", startIndex+1, endIndex))
+
+	}
+	return nil
+}
+
 // 修改
 func Up_TaskData(T_task_id string, Id string, T_t string, T_rh string, T_time string) bool {
 
@@ -971,15 +1004,18 @@ func InsertTaskData_TH(T_task_id string, T_switch_t, T_switch_h bool, d TaskData
 }
 
 // DeleteTaskDataByTimeRange 删除时间范围内的数据
-func DeleteTaskDataByTimeRange(T_task_id, sn string, id string, start, end string) {
-	sqlStatement := fmt.Sprintf("delete from z_task_data_%s where t_time between '%s' and '%s' and t_id = '%s' and t_sn = '%s'", T_task_id, start, end, id, sn)
+func DeleteTaskDataByTimeRange(T_task_id, sn string, id string, startTime, endTime string) {
+	sqlStatement := fmt.Sprintf("delete from z_task_data_%s where t_id = '%s' and t_sn = '%s'", T_task_id, id, sn)
+	if len(startTime) > 0 && len(endTime) > 0 {
+		sqlStatement += " AND t_time BETWEEN '" + startTime + "' AND '" + endTime + "'"
+	}
 	o := orm.NewOrm()
 	exec, err := o.Raw(sqlStatement).Exec()
 	if err != nil {
 		fmt.Println(err.Error())
 	}
 	affected, _ := exec.RowsAffected()
-	fmt.Printf("从%s~%s时间段删除了%d条数据", start, end, affected)
+	logs.Println(fmt.Sprintf("从 %s - %s 时间段删除了%d条数据", startTime, endTime, affected))
 }
 
 // UpdateTaskDataTemperatureAndHumidityRandom 随机更新
@@ -996,9 +1032,13 @@ func UpdateTaskDataTemperatureAndHumidityRandom(T_task_id, sn, id, startTime, en
 	fmt.Println("执行更新行数:", affected)
 }
 
-// UpdateTaskDataTemperatureAndHumidity 更新设备探头数据温湿度
+// UpdateTaskDataTemperatureAndHumidity 更新设备探头数据温湿度 固定偏移
 func UpdateTaskDataTemperatureAndHumidity(T_task_id, sn, id, startTime, endTime string, temperature, humidity float64) {
-	sqlStatement := fmt.Sprintf("update z_task_data_%s set t_t = t_t + %f , t_rh = t_rh + %f where t_id = '%s' and  t_sn = '%s' and t_time BETWEEN '%s' and '%s'", T_task_id, temperature, humidity, id, sn, startTime, endTime)
+	sqlStatement := fmt.Sprintf("update z_task_data_%s set t_t = t_t + %f , t_rh = t_rh + %f where t_id = '%s' and  t_sn = '%s' ", T_task_id, temperature, humidity, id, sn)
+	if len(startTime) > 0 && len(endTime) > 0 {
+		sqlStatement += " AND t_time BETWEEN '" + startTime + "' AND '" + endTime + "'"
+	}
+
 	o := orm.NewOrm()
 
 	exec, err := o.Raw(sqlStatement).Exec()
@@ -1062,8 +1102,10 @@ func Read_TaskData_T_Min_Max(T_task_id string, SN string, T_id string, Time_star
 // UpdateTaskDataTemperatureAndHumidityByGeometric 更新设备探头数据温湿度 等比缩放
 func UpdateTaskDataTemperatureAndHumidityByGeometric(T_task_id, sn, id, startTime, endTime string, temperature, humidity float64) {
 
-	sqlStatement := fmt.Sprintf("update z_task_data_%s set t_t = t_t * %f , t_rh = t_rh * %f where t_id = '%s' and  t_sn = '%s' and t_time BETWEEN '%s' and '%s'", T_task_id, temperature, humidity, id, sn, startTime, endTime)
-
+	sqlStatement := fmt.Sprintf("update z_task_data_%s set t_t = t_t * %f , t_rh = t_rh * %f where t_id = '%s' and  t_sn = '%s' ", T_task_id, temperature, humidity, id, sn)
+	if len(startTime) > 0 && len(endTime) > 0 {
+		sqlStatement += " AND t_time BETWEEN '" + startTime + "' AND '" + endTime + "'"
+	}
 	o := orm.NewOrm()
 
 	exec, err := o.Raw(sqlStatement).Exec()
@@ -1076,10 +1118,12 @@ func UpdateTaskDataTemperatureAndHumidityByGeometric(T_task_id, sn, id, startTim
 	}
 	fmt.Printf("影响了%d行\n", affected)
 }
-func UpdateTaskDataTemperatureAndHumidityByGeometric_id(T_task_id, id, startTime, endTime string, temperature float64) {
-
-	sqlStatement := fmt.Sprintf("update z_task_data_%s set t_t = t_t * %f where t_id = '%s' and t_time BETWEEN '%s' and '%s'", T_task_id, temperature, id, startTime, endTime)
+func UpdateTaskDataTemperatureAndHumidityByGeometric_id(T_task_id, id, startTime, endTime string, compress float64) {
 
+	sqlStatement := fmt.Sprintf("update z_task_data_%s set t_t = t_t * %f where t_id = '%s' ", T_task_id, compress, id)
+	if len(startTime) > 0 && len(endTime) > 0 {
+		sqlStatement += " AND t_time BETWEEN '" + startTime + "' AND '" + endTime + "'"
+	}
 	o := orm.NewOrm()
 
 	exec, err := o.Raw(sqlStatement).Exec()
@@ -1093,15 +1137,18 @@ func UpdateTaskDataTemperatureAndHumidityByGeometric_id(T_task_id, id, startTime
 	fmt.Printf("影响了%d行\n", affected)
 }
 
-// UpdateTaskDataTemperatureAndHumidityByGeometric 更新设备探头数据温湿度 等比缩放
+// UpdateTaskDataTemperatureAndHumidityByGeometric 更新设备探头数据温湿度 偏移
 func UpdateTaskDataTemperatureAndHumidityByGeometricAVG(T_task_id, id, startTime, endTime string, temperature float64) {
 
 	sqlStatement := ""
 	if temperature > 0 {
-		sqlStatement = fmt.Sprintf("update z_task_data_%s set t_t = t_t + %f  where t_id = '%s' and t_time BETWEEN '%s' and '%s'", T_task_id, temperature, id, startTime, endTime)
+		sqlStatement = fmt.Sprintf("update z_task_data_%s set t_t = t_t + %f  where t_id = '%s' ", T_task_id, temperature, id)
 	} else {
-		sqlStatement = fmt.Sprintf("update z_task_data_%s set t_t = t_t %f  where t_id = '%s' and t_time BETWEEN '%s' and '%s'", T_task_id, temperature, id, startTime, endTime)
+		sqlStatement = fmt.Sprintf("update z_task_data_%s set t_t = t_t %f  where t_id = '%s' ", T_task_id, temperature, id)
+	}
 
+	if len(startTime) > 0 && len(endTime) > 0 {
+		sqlStatement += " AND t_time BETWEEN '" + startTime + "' AND '" + endTime + "'"
 	}
 	o := orm.NewOrm()
 
@@ -1823,7 +1870,8 @@ func GroupDataByTSN(data []TaskData_) map[string][]TaskData_ {
 	return groupedData
 }
 
-// 计算样本标准差(n-1分母)
+//计算样本标准差(n-1分母)
+
 func calculateStdDev(values []float64) float64 {
 	n := len(values)
 	if n < 2 {
@@ -1849,7 +1897,7 @@ func calculateStdDev(values []float64) float64 {
 }
 
 // 获取波动度最大的三条数据集
-func GetTopThreeWithTheGreatestFluctuations(data []TaskData_) string {
+func GetTheGreatestFluctuations(data []TaskData_, num int) string {
 	// 存储波动度结果
 	type Result struct {
 		T_sn       string
@@ -1857,7 +1905,7 @@ func GetTopThreeWithTheGreatestFluctuations(data []TaskData_) string {
 		DataPoints []TaskData_
 	}
 	dataSets := GroupDataByTSN(data)
-	results := make([]Result, len(dataSets))
+	results := make([]Result, 0)
 
 	// 计算每条数据集的波动度
 	for T_sn, dataset := range dataSets {
@@ -1866,8 +1914,9 @@ func GetTopThreeWithTheGreatestFluctuations(data []TaskData_) string {
 			values[j] = float64(dp.T_t)
 		}
 		results = append(results, Result{
-			T_sn:       T_sn,
-			StdDev:     calculateStdDev(values),
+			T_sn: T_sn,
+			//StdDev:     calculateStdDev(values),
+			StdDev:     standardDeviation(values),
 			DataPoints: dataset,
 		})
 	}
@@ -1877,14 +1926,12 @@ func GetTopThreeWithTheGreatestFluctuations(data []TaskData_) string {
 		return results[i].StdDev > results[j].StdDev
 	})
 
-	// 输出波动最大的三条
-	fmt.Println("波动最大的三条数据集:")
-	for i, res := range results[:3] {
-		fmt.Printf("%d. 数据集%d (标准差=%.4f)\n", i+1, res.T_sn, res.StdDev)
-	}
-	snList := make([]string, 3)
-	if len(results) >= 3 {
-		snList = []string{results[0].T_sn, results[1].T_sn, results[2].T_sn}
+	snList := make([]string, num)
+	if len(results) >= num {
+		for i := 0; i < num; i++ {
+			fmt.Println(results[i].T_sn, results[i].StdDev)
+			snList = append(snList, results[i].T_sn)
+		}
 	} else {
 		for _, v := range results {
 			snList = append(snList, v.T_sn)
@@ -1893,3 +1940,20 @@ func GetTopThreeWithTheGreatestFluctuations(data []TaskData_) string {
 
 	return strings.Join(snList, "|")
 }
+
+// 计算平均值
+func mean(data []float64) float64 {
+	sum := 0.0
+	for _, value := range data {
+		sum += value
+	}
+	return sum / float64(len(data))
+}
+func standardDeviation(data []float64) float64 {
+	meanVal := mean(data)
+	var sumSquares float64
+	for _, value := range data {
+		sumSquares += math.Pow(value-meanVal, 2)
+	}
+	return math.Sqrt(sumSquares / float64(len(data)))
+}