import statistics import uuid from collections import defaultdict from datetime import datetime, timedelta import pandas as pd from irrgiation.db_connect import query_postgresql_to_dataframe, dataframe_to_postgresql_batch,update_irrigation_data from irrgiation.weatherAndSoilDataRequest import getWeatherAndSoilData, loginAuth, dateToTimestamp, get_soil_data_dk1, \ getFutureWeather, weather_params, get_soil_data_dk2 from irrgiation.dailyEvaporation import get_daily_kc, cal_et0_List, calculate_etc_List, export_etc_et0_date, \ cal_soil_fc_wp, estimate_mad_from_et, cal_stagebyDate, calculate_average_root_length,calculate_etc_List_new from irrgiation.mathuntils import day_of_year from irrgiation.soil_Ke import calculate_ke,calculate_D_ei from irrgiation.crop_growth_stages import crop_growth_stages #解析数据接口,计算均值、最大、最小值 def analy_soil_data(data): soil_result = {} for key in data: daily_data = defaultdict(lambda: defaultdict(list)) for metric, entries in data[key].items(): for entry in entries: dt = datetime.strptime(entry["datetime"], "%Y-%m-%d %H:%M:%S") date_key = dt.date() # 按日期分组 value = float(entry["value"]) daily_data[date_key][metric].append(value) result = {} for date, metrics in daily_data.items(): date_stats = {} for metric, values in metrics.items(): date_stats[metric] = { "max": max(values), "min": min(values), "mean": statistics.mean(values), 'count': len(values), 'sum': sum(values) } result[str(date)] = date_stats # 将日期转为字符串作为键 soil_result[key] = result return soil_result #获取地块6个传感器的土壤湿度均值 def analy_soil_data_mean(soil_data): result = defaultdict(lambda: { "SOIL_MOISTURE_SURFACE": [], "SOIL_MOISTURE_MIDDLE": [], "SOIL_MOISTURE_BOTTOM": [] }) # 填充数据 for sensor, dates in soil_data.items(): for date, layers in dates.items(): result[date]["SOIL_MOISTURE_SURFACE"].append(layers["SOIL_MOISTURE_SURFACE"]["mean"]) result[date]["SOIL_MOISTURE_MIDDLE"].append(layers["SOIL_MOISTURE_MIDDLE"]["mean"]) result[date]["SOIL_MOISTURE_BOTTOM"].append(layers["SOIL_MOISTURE_BOTTOM"]["mean"]) # 转换为普通字典 final_result = dict(result) result_soil = {} for date, layers in final_result.items(): result_soil[date] = { "SOIL_MOISTURE_SURFACE_MEAN": sum(layers["SOIL_MOISTURE_SURFACE"]) / len(layers["SOIL_MOISTURE_SURFACE"]), "SOIL_MOISTURE_MIDDLE_MEAN": sum(layers["SOIL_MOISTURE_MIDDLE"]) / len(layers["SOIL_MOISTURE_MIDDLE"]), "SOIL_MOISTURE_BOTTOM_MEAN": sum(layers["SOIL_MOISTURE_BOTTOM"]) / len(layers["SOIL_MOISTURE_BOTTOM"]) } return final_result, result_soil def analy_soil_dataNight_mean(soil_data): daily_means = defaultdict(lambda: defaultdict(list)) # 计算平均值 for sensor, measurements in soil_data.items(): for measure_type, dates in measurements.items(): for date, value in dates.items(): daily_means[date][measure_type].append(float(value)) # 计算并格式化结果 result = {} for date, measures in daily_means.items(): result[date] = { f"{measure_type}_MEAN": round(sum(values) / len(values), 2) for measure_type, values in measures.items() } return result #获取地块6个传感器中土壤湿度最大值 def analy_soil_data_max(soil_data): result = defaultdict(lambda: { "SOIL_MOISTURE_SURFACE": [], "SOIL_MOISTURE_MIDDLE": [], "SOIL_MOISTURE_BOTTOM": [] }) # 填充数据 for sensor, dates in soil_data.items(): for date, layers in dates.items(): result[date]["SOIL_MOISTURE_SURFACE"].append(layers["SOIL_MOISTURE_SURFACE"]["mean"]) result[date]["SOIL_MOISTURE_MIDDLE"].append(layers["SOIL_MOISTURE_MIDDLE"]["mean"]) result[date]["SOIL_MOISTURE_BOTTOM"].append(layers["SOIL_MOISTURE_BOTTOM"]["mean"]) # 转换为普通字典 final_result = dict(result) result_soil = {} for date, layers in final_result.items(): result_soil[date] = { "SOIL_MOISTURE_SURFACE_MEAN": max(layers["SOIL_MOISTURE_SURFACE"]), "SOIL_MOISTURE_MIDDLE_MEAN": max(layers["SOIL_MOISTURE_MIDDLE"]), "SOIL_MOISTURE_BOTTOM_MEAN": max(layers["SOIL_MOISTURE_BOTTOM"]) } return final_result, result_soil def get_soil_data_night_eyveryDay(data): daily_data = {} for sersor in data: data_depth = {} for key in data[sersor]: target_time = (21, 59, 59) result = {} # 时、分、秒元组 daily_records = {} # 临时存储每天的所有记录,用于找不到22点数据时获取最新记录 for record in data[sersor][key]: try: dt = datetime.strptime(record["datetime"], "%Y-%m-%d %H:%M:%S") date_str = record["datetime"].split(" ")[0] # 提取日期部分 # 严格匹配 02:00:00 # 提取时间部分(时、分、秒) current_time = (dt.hour, dt.minute, dt.second) # 存储每天的所有记录(按时间排序) if date_str not in daily_records: daily_records[date_str] = [] daily_records[date_str].append((dt, record['value'])) # 比较时间部分 if current_time >= target_time: if date_str not in result: result[date_str] = record['value'] except: continue # 对于没有22点数据的日期,取当天最新的一条数据 for date_str in daily_records: if date_str not in result and daily_records[date_str]: daily_records[date_str].sort(key=lambda x: x[0]) # 按datetime排序 result[date_str] = daily_records[date_str][-1][1] # 取最后一个值 data_depth[key] = result daily_data[sersor] = data_depth return daily_data def analyze_weather_data1(data): # 1. 按日期分组数据 daily_data = defaultdict(lambda: defaultdict(list)) for metric, entries in data.items(): for entry in entries: dt = datetime.strptime(entry["datetime"], "%Y-%m-%d %H:%M:%S") date_key = dt.date() # 按日期分组 if metric == "AIR_LUX": value = float(entry["value_solar"]) else: value = float(entry["value"]) daily_data[date_key][metric].append(value) # 2. 计算每日统计值 result = {} for date, metrics in daily_data.items(): date_stats = {} for metric, values in metrics.items(): date_stats[metric] = { "max": max(values), "min": min(values), "mean": statistics.mean(values), 'count': len(values), 'sum': sum(values) } result[str(date)] = date_stats # 将日期转为字符串作为键 return result # 获取彭曼公式的入参 def get_params(start_date, monitor_date, data): delta = monitor_date - start_date days = delta.days dates = [start_date + timedelta(days=i) for i in range(days)] date_strings = [date.strftime("%Y-%m-%d") for date in dates] date_params = {} for date in date_strings: result_params = get_weather_params(data, date) date_params[date] = result_params return date_params def get_weather_params(data, date): result = {} elevation = 865 # 海拔(m) lat = 41.34252110189814 # 纬度(度) #计算当前日期位于当年的多少天 doy = day_of_year(date) for item in data['AIR_LUX']: item['value_solar'] = float(item['value']) * 0.0081 * 3600 data_tj = analyze_weather_data1(data) data_tj_date = data_tj[date]; tmax = data_tj_date['AIR_TEMPERATURE']['max'] tmin = data_tj_date['AIR_TEMPERATURE']['min'] tmean = data_tj_date['AIR_TEMPERATURE']['mean'] rh_mean = data_tj_date['AIR_HUMIDITY']['mean'] wind_speed = data_tj_date['WIND_SPEED']['mean'] solar = data_tj_date['AIR_LUX']['sum'] / 1000000 result['tmax'] = round(tmax, 3) result['tmin'] = round(tmin, 3) result['tmean'] = round(tmean, 3) result['rh_mean'] = round(rh_mean, 3) result['wind_speed'] = round(wind_speed, 3)*0.94 result['solar_rad'] = round(solar, 3) result['elevation'] = elevation result['lat'] = round(lat, 3) result['doy'] = doy return result # 判断是否需要灌溉 def isNeedirrigate(df, qx_coff, soil_coff,Di_1,zwlx_growth_stages): df['RD'] = 0.0 df['Di'] = 0.0 df['Di-1'] = Di_1 df['mad'] = 0.0 df['irrigation_depth'] = 0.0 df['irrigation_acre'] = 0.0 df['isNeedirrigate'] = False df['Reset_Flag'] = False # df['irrigate_sd_predict'] = 0.0 df['f_t'] = 0.0 df['f_js'] = 0.0 df['f_soil'] = 0.0 for i in range(len(df)): # 设置Di-1(前一天累计值) if i > 0: df.at[i, 'Di-1'] = df.at[i - 1, 'Di'] # 计算当前累计值(Di-1 + 当天ETc) raw, rd, mad, k_rain = cal_raw(df.at[i, 'ETc'], df.at[i, 'Date'],zwlx_growth_stages) if df.at[i, 'rain_effective']<5: df.at[i, 'rain_effective'] = 0 else: df.at[i, 'rain_effective'] = df.at[i, 'rain_effective'] * k_rain current_cum = df.at[i, 'Di-1'] + df.at[i, 'ETc']- df.at[i, 'rain_effective'] df['RD'] = rd df.at[i,'mad'] = mad df.at[i, 'raw'] = round(raw, 3) f_t = qx_coff[df.at[i, 'Date']]['qw'] f_js = qx_coff[df.at[i, 'Date']]['js'] f_soil = soil_coff[df.at[i, 'Date']] raw_adj = cal_raw_adjust(raw, f_t, f_js, f_soil) df.at[i, 'f_t'] = f_t df.at[i, 'f_js'] = f_js df.at[i, 'f_soil'] = f_soil df.at[i, 'raw_adjust'] = round(raw_adj, 3) # 判断是否需要重置 if current_cum > raw_adj: df.at[i, 'Reset_Flag'] = True df.at[i, 'irrigation_depth'] = round(current_cum, 3) df.at[i, 'isNeedirrigate'] = True df.at[i, 'Di'] = 0 # 保留当天ETc值 df.at[i, 'irrigation_acre'] = round((current_cum*667/1000),3) else: df.at[i, 'Di'] = round(current_cum, 3) # 正常累加 return df def cal_raw(etc, monitor_date,zwlx_growth_stages): theta_fc, theta_wp = cal_soil_fc_wp() stage, details,hight,k_rain= cal_stagebyDate(monitor_date,zwlx_growth_stages) rd = calculate_average_root_length(details) mad = estimate_mad_from_et(etc) raw = mad * (theta_fc - theta_wp) * rd * 10 return raw, rd,mad,k_rain def cal_raw_adjust(raw, f_t, f_rain, f_soil): raw_adjust = raw * f_soil * f_t * f_rain return raw_adjust def cal_qxcoefficient_adjust(start_date, monitor_date, qx_data): qx_coefficient = {} current_date = start_date qxData_filter = {} for key in qx_data: if key == "AIR_TEMPERATURE" or key == "RAIN_FALL_REALTIME": qxData_filter[key] = qx_data[key] qxData_filter_tj = analyze_weather_data1(qxData_filter) now_date = datetime.now().date() while current_date < monitor_date: qx_futureData = [] result = {} if (current_date + timedelta(days=3)).date() < now_date: start = datetime.strptime((current_date + timedelta(days=1)).strftime("%Y-%m-%d"), "%Y-%m-%d") end = datetime.strptime((current_date + timedelta(days=3)).strftime("%Y-%m-%d"), "%Y-%m-%d") # 筛选日期范围内的数据 filter = { date: values for date, values in qxData_filter_tj.items() if start <= datetime.strptime(date, "%Y-%m-%d") <= end } qx_futureData = transform_data(filter) else: try: # print(f"进入else分支: {current_date}") qx_futureData = getFutureWeather(current_date) except Exception as e: # print(f"else分支异常: {e}") raise # 保留异常以便调试 qw_mean = (qx_futureData['qw_day1']['mean'] + qx_futureData['qw_day2']['mean'] + qx_futureData['qw_day3']['mean']) / 3 js_sum = qx_futureData['js_day1']['max'] + qx_futureData['js_day2']['max'] + qx_futureData['js_day3']['max'] qw_coff = 1.0 js_coff = 1.0 if qw_mean < 10: qw_coff = 1.1 elif 10 < qw_mean <= 25: qw_coff = 1 elif 25 < qw_mean <= 30: qw_coff = 0.85 else: qw_coff = 0.75 if js_sum <= 5: js_coff = 1.0 # 少雨 elif 5 < js_sum <= 10: js_coff = 1.2 # 中雨 elif 10 < js_sum <= 20: js_coff = 1.4 # 大雨 else: js_coff = 1.6 # 暴雨 result['qw'] = qw_coff result['js'] = js_coff qx_coefficient[current_date.strftime("%Y-%m-%d")] = result current_date = current_date + timedelta(days=1) return qx_coefficient def transform_data(original_data): transformed = {} # 处理温度数据 (qw_day) for i, (date, metrics) in enumerate(original_data.items(), 1): temp_data = metrics["AIR_TEMPERATURE"] transformed[f"qw_day{i}"] = { "max": round(temp_data["max"], 2), "min": round(temp_data["min"], 2), "mean": round(temp_data["mean"], 2), "sum": round(temp_data["sum"], 2) } # 处理降雨数据 (js_day) for i, (date, metrics) in enumerate(original_data.items(), 1): rain_data = metrics["RAIN_FALL_REALTIME"] transformed[f"js_day{i}"] = { "max": round(rain_data["max"], 2), "min": round(rain_data["min"], 2), "mean": round(rain_data["mean"], 2), "sum": round(rain_data["sum"], 2) } return transformed def cal_soil_coff(soil_data): soil_data_coff = {} for sensor in soil_data: for date in soil_data[sensor]: soil_cof = 1.0 sd_surf = float(soil_data['SOIL_MOISTURE_SURFACE'][date]) sd_mid = float(soil_data['SOIL_MOISTURE_MIDDLE'][date]) if sd_surf < 10: soil_cof = 0.5 if 10 0 and rain < 4: fw = 0.35 elif I > 0 and rain < 4: fw = 1 elif rain > 4 and I == 0: fw = 1 else: fw = ke_data[prev_date_key]['fw'] et0 = 0.0 kc = 0.0 if i < len(et0_list): et0 = et0_list[i] kc = kc_list[i] ke,few=calculate_ke(hight, u2, rh_min, kc, DE_i_1, REW, fw, theta_fc,theta_wp) et_soil=ke*et0 DE_i = calculate_D_ei(DE_i_1, rain, I,et_soil, fw,few) #创建当天的数据字典 daily_data = { 'ke': ke, 'DE_i': DE_i, 'et0': et0, 'et_soil': et_soil, 'fw':fw, "rain":rain, "irrigation":I } ke_data[date_key]=daily_data current_date = current_date + timedelta(days=1) i=i+1 return ke_data # 单天监测 def cal_irrigationByDay(zwlx_name,dkname,start_date,end_date,soil_key,weather_key,irrigation_really): yesterday_date=(start_date - timedelta(days=1)).strftime("%Y-%m-%d") condition = {"Date": yesterday_date,"dkbm":dkname} df=query_postgresql_to_dataframe(condition) Di_1 = 0 if irrigation_really>0: Di_1 = 0 update_irrigation_data(yesterday_date,dkname,"irrigation_really",irrigation_really) else: # 将Date列转换为日期时间类型 df['Date'] = pd.to_datetime(df['Date']) if len(df[df.Date == (start_date - timedelta(days=1))])!=0: isNeedjg=df[df.Date == (start_date- timedelta(days=1))]['isNeedirrigate'].values[0] if isNeedjg: Di_1 = df[df.Date == (start_date - timedelta(days=1))]['Di-1'].values[0]+df[df.Date == (start_date - timedelta(days=1))]['ETc'].values[0] else: Di_1 = df[df.Date == (start_date - timedelta(days=1))]['Di'].values[0] dataframe=cal_dk_isNeegirrigate_Day(zwlx_name,dkname,soil_key,start_date,end_date,Di_1,weather_key) condition_new = {"Date": start_date.strftime("%Y-%m-%d"), "dkbm": dkname} df_query=query_postgresql_to_dataframe(condition_new) if len(df_query)==0: dataframe_to_postgresql_batch(dataframe) else: print("库表中已存在该数据") return dataframe if __name__ == "__main__": #调用气象数据接口--获取具体日期的气象数据(气象) # auth_token = loginAuth() start_date = datetime(2025, 7, 16) monitor_date = datetime(2025, 7, 17) dk_name = "5" zwlx_name="甘草" soil_key = "8637b970-561b-11f0-a556-4f10f26fc07f" weather_key="18d121f0-561b-11f0-a556-4f10f26fc07f" irrigation_really=5 cal_irrigationByDay(zwlx_name,dk_name,start_date,monitor_date,soil_key,weather_key,irrigation_really) # cal_dk_isNeegirrigate(dk_name, planting_date, monitor_date,0)