optimize.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. import os
  2. from datetime import datetime,timedelta
  3. from pathlib import Path
  4. from pprint import pprint
  5. import pandas as pd
  6. from ...model.DHU.DHU_AB import DHU_AB
  7. from .config_reader import ConfigReader
  8. from ...tools.data_loader import DataLoader
  9. NOW = datetime.now().replace(second=0,microsecond=0)
  10. def optimize(*inputs,config=None):
  11. config = {} if config is None else config
  12. if '__LOCAL' in config.keys():
  13. config_reader_path = config['__LOCAL']
  14. data_URL = config['__URL']
  15. else:
  16. config_reader_path = '/mnt/workflow_data'
  17. data_URL = 'http://basedataportal-svc:8080/data/getpointsdata'
  18. config_reader = ConfigReader(path=f'{config_reader_path}/DHU配置.xlsx')
  19. ALL_RESULT = {
  20. 'EXCEPTION':{
  21. 'Mod' : {},
  22. 'Data_Room': {},
  23. 'Data_ATD' : {},
  24. 'Opt' : {},
  25. 'Push' : {}
  26. },
  27. 'STATUS':{
  28. 'Mode_Steady': [],
  29. 'Mode_Low' : [],
  30. 'Mode_stop' : []
  31. }
  32. }
  33. for each_eaup_name,each_eaup_name_short in zip(
  34. config_reader.all_equp_names,
  35. config_reader.all_equp_names_short
  36. ):
  37. # 加载模型
  38. # 加载数据
  39. # 运行判断
  40. # 稳态判断:房间露点设定值与反馈值是否接近
  41. # 模型调整
  42. # 模型判断:模型精度是否满足要求
  43. # 模式判断:
  44. # 1. 基于当前露点优化模式:基于房间露点设定值减偏差
  45. # 2. 快速提升送风露点模式:约束送风露点保持不变
  46. if not config_reader.get_app_info(each_eaup_name,'实时优化','开始实时优化','bool'):
  47. continue
  48. each_equp_type = config_reader.get_equp_info(each_eaup_name,key='设备类型',info_type='str')
  49. # 加载模型
  50. try:
  51. MODEL = load_model(
  52. each_eaup_name = each_eaup_name,
  53. config_reader = config_reader,
  54. config_reader_path = config_reader_path
  55. )
  56. except Exception as e:
  57. ALL_RESULT['EXCEPTION']['Mod'][each_eaup_name] = e
  58. continue
  59. try:
  60. data_room = load_data_room(
  61. each_eaup_name = each_eaup_name,
  62. each_equp_type = each_equp_type,
  63. config_reader = config_reader,
  64. config_reader_path = config_reader_path,
  65. data_URL = data_URL
  66. )
  67. if data_room['is_room_Dew_steady']:
  68. DewOut_constrain = 'coil_3_DoutA-[coil_3_DoutA]<0'
  69. ALL_RESULT['STATUS']['Mode_Steady'].append(each_eaup_name)
  70. elif data_room['is_room_Dew_low']:
  71. room_Dew_SP = data_room['room_Dew_SP']
  72. #TODO 这个4度比较粗糙,待改进
  73. DewOut_constrain = f'coil_3_DoutA-{room_Dew_SP-4}<0'
  74. ALL_RESULT['STATUS']['Mode_Low'].append(each_eaup_name)
  75. else:
  76. ALL_RESULT['STATUS']['Mode_stop'].append(each_eaup_name)
  77. continue
  78. except Exception as e:
  79. ALL_RESULT['STATUS']['Data_Room'][each_eaup_name] = e
  80. continue
  81. try:
  82. data_dhu = load_data_dhu(
  83. each_eaup_name = each_eaup_name,
  84. each_equp_type = each_equp_type,
  85. config_reader = config_reader,
  86. config_reader_path = config_reader_path,
  87. data_URL = data_URL
  88. )
  89. except Exception as e:
  90. ALL_RESULT['EXCEPTION']['Data_ATD'][each_eaup_name] = e
  91. continue
  92. try:
  93. opt_result = optimize_dhu(
  94. MODEL = MODEL,
  95. data_cur = data_dhu,
  96. DewOut_constrain = DewOut_constrain,
  97. config_reader = config_reader,
  98. each_eaup_name = each_eaup_name,
  99. each_equp_type = each_equp_type
  100. )
  101. except Exception as e:
  102. ALL_RESULT['EXCEPTION']['Opt'][each_eaup_name] = e
  103. continue
  104. try:
  105. push_result(
  106. each_eaup_name = each_eaup_name,
  107. each_eaup_name_short = each_eaup_name_short,
  108. each_equp_type = each_equp_type,
  109. config_reader = config_reader,
  110. opt_result = opt_result,
  111. data_cur = data_dhu
  112. )
  113. except Exception as e:
  114. ALL_RESULT['EXCEPTION']['Push'][each_eaup_name] = e
  115. continue
  116. pprint(ALL_RESULT)
  117. def load_model(
  118. each_eaup_name,
  119. config_reader:ConfigReader,
  120. config_reader_path
  121. ):
  122. adjust_equp_name = config_reader.get_equp_info(each_eaup_name,'替代模型','str')
  123. print('abc',adjust_equp_name)
  124. if adjust_equp_name in config_reader.all_equp_names_total:
  125. print(f'{each_eaup_name}使用替代模型{adjust_equp_name}')
  126. each_eaup_name = adjust_equp_name
  127. else:
  128. pass
  129. if config_reader.get_app_info(
  130. each_eaup_name,
  131. app_type = '实时优化',
  132. key = '使用临时模型',
  133. info_type = 'bool'
  134. ):
  135. # 从文件夹中获取临时模型
  136. MODEL = DHU_AB.load(path=f'{config_reader_path}/model/{each_eaup_name}.pkl')
  137. else:
  138. MODEL = DHU_AB.load_from_platform(
  139. source = 'id',
  140. model_id = config_reader.get_equp_info(
  141. equp_name = each_eaup_name,
  142. key = '模型编号',
  143. info_type = 'str'
  144. )
  145. )
  146. return MODEL
  147. def load_data_room(
  148. each_eaup_name,
  149. each_equp_type,
  150. config_reader,
  151. config_reader_path,
  152. data_URL
  153. ):
  154. room_steady_len = config_reader.get_app_info(each_eaup_name,'实时优化','房间稳态判断时长','float')
  155. room_data_loader = DataLoader(
  156. path = f'{config_reader_path}/data/optimize/data_cur/',
  157. start_time = NOW - timedelta(minutes=room_steady_len),
  158. end_time = NOW
  159. )
  160. room_data_loader.download_equp_data(
  161. equp_name = each_eaup_name,
  162. point = config_reader.get_equp_point(each_eaup_name,each_equp_type,equp_class=['C']),
  163. url = data_URL,
  164. clean_cache = True
  165. )
  166. room_data = room_data_loader.get_equp_data(each_eaup_name)
  167. room_Dew_SP_adj = config_reader.get_app_info(each_eaup_name,'实时优化','房间露点设定值偏差','float')
  168. room_Dew_SP = room_data.room_DSP.mean() + room_Dew_SP_adj
  169. room_Dew_PV = room_data.room_DPV.mean()
  170. room_Dew_diff_dwlim = config_reader.get_app_info(each_eaup_name,'实时优化','房间露点过低阈值','float')
  171. # 模式判断
  172. is_room_Dew_steady = (room_Dew_PV < room_Dew_SP + 0.5) or (room_Dew_PV > room_Dew_SP - 0.5)
  173. is_room_Dew_low = room_Dew_PV - room_Dew_SP < room_Dew_diff_dwlim
  174. data_room = {
  175. 'is_room_Dew_steady': is_room_Dew_steady,
  176. 'is_room_Dew_low' : is_room_Dew_low,
  177. 'room_Dew_SP' : room_Dew_SP
  178. }
  179. return data_room
  180. def load_data_dhu(
  181. each_eaup_name,
  182. each_equp_type,
  183. config_reader,
  184. config_reader_path,
  185. data_URL
  186. ):
  187. dhu_steady_len = config_reader.get_app_info(each_eaup_name,'实时优化','除湿机工况均值时长','float')
  188. data_input_point = config_reader.get_equp_point(each_eaup_name,each_equp_type,equp_class=['A','B'])
  189. data_cur = (
  190. DataLoader(
  191. path = f'{config_reader_path}/data/optimize/data_cur/',
  192. start_time = NOW - timedelta(minutes=dhu_steady_len),
  193. end_time = NOW
  194. )
  195. .download_equp_data(
  196. equp_name = each_eaup_name,
  197. point = data_input_point,
  198. url = data_URL,
  199. clean_cache = True
  200. )
  201. .get_equp_data(
  202. equp_name = each_eaup_name,
  203. )
  204. .mean(axis=0)
  205. .to_frame().T
  206. )
  207. return data_cur
  208. def optimize_dhu(
  209. MODEL,
  210. data_cur,
  211. DewOut_constrain,
  212. config_reader,
  213. each_eaup_name,
  214. each_equp_type
  215. ):
  216. # 模型精度判断
  217. predict = MODEL.predict_system(input_data=data_cur)
  218. TVP_data = (
  219. predict.T.set_axis(['pred'],axis=1)
  220. .join(
  221. data_cur.T.set_axis(['real'],axis=1),
  222. how = 'left'
  223. )
  224. .dropna(axis=0)
  225. .assign(diff=lambda x: x['pred'] - x['real'])
  226. )
  227. print(TVP_data)
  228. # 实时优化
  229. constrains = [DewOut_constrain]
  230. opt_res = MODEL.optimize(
  231. cur_input_data=data_cur,
  232. wheel_1_TinR=(
  233. config_reader.get_app_info(each_eaup_name,'实时优化','前再生盘管温度下限','float'),
  234. config_reader.get_app_info(each_eaup_name,'实时优化','前再生盘管温度上限','float')
  235. ),
  236. wheel_2_TinR=(
  237. config_reader.get_app_info(each_eaup_name,'实时优化','后再生盘管温度下限','float'),
  238. config_reader.get_app_info(each_eaup_name,'实时优化','后再生盘管温度上限','float')
  239. ),
  240. fan_2_Hz = None,
  241. constrains = constrains,
  242. logging = False,
  243. target = 'summary_waste',
  244. target_min = True
  245. )
  246. opt_summary = opt_res['opt_summary']
  247. opt_var = opt_res['opt_var']
  248. print(opt_summary)
  249. print(opt_var)
  250. return {
  251. 'opt_summary': opt_summary,
  252. 'opt_var' : opt_var,
  253. }
  254. def push_result(
  255. each_eaup_name,
  256. each_eaup_name_short,
  257. each_equp_type,
  258. config_reader:ConfigReader,
  259. opt_result:dict,
  260. data_cur:pd.DataFrame
  261. ):
  262. equp_point = config_reader.get_equp_point(each_eaup_name,each_equp_type,equp_class=['D'])
  263. if each_equp_type in ['DHU_A','DHU_B']:
  264. rcmd = [
  265. {
  266. 'name' : '前再生加热温度',
  267. 'rcmd_value': opt_result['opt_var'][0].iat[0,0],
  268. 'children' : [
  269. {
  270. 'name' : '前再生加热温度',
  271. 'rcmd_value': opt_result['opt_var'][0].round(1).iat[0,0],
  272. 'curr_value': data_cur.loc[:,['wheel_1_TinR']].round(1).iat[0,0],
  273. 'point_id' : f'{each_eaup_name}_{equp_point["wheel_1_TinR_AISP"]}'
  274. }
  275. ]
  276. },
  277. {
  278. 'name' : '后再生加热温度',
  279. 'rcmd_value': opt_result['opt_var'][1].iat[0,0],
  280. 'children' : [
  281. {
  282. 'name' : '后再生加热温度',
  283. 'rcmd_value': opt_result['opt_var'][1].round(1).iat[0,0],
  284. 'curr_value': data_cur.loc[:,['wheel_2_TinR']].round(1).iat[0,0],
  285. 'point_id' : f'{each_eaup_name}_{equp_point["wheel_2_TinR_AISP"]}'
  286. }
  287. ]
  288. },
  289. ]
  290. else:
  291. raise Exception('MODEL_TYPE_ERROR')
  292. if config_reader.get_app_info(each_eaup_name,'实时优化','推送策略','bool'):
  293. add_ai_rcmd_operation(
  294. code = each_eaup_name_short,
  295. job_id = os.environ.get('JOB_ID', None),
  296. rcmd = rcmd,
  297. custom_details = []
  298. )
  299. else:
  300. pprint(rcmd)
  301. def add_ai_rcmd_operation(code,job_id,rcmd,custom_details):
  302. from workflowlib import requests
  303. json_info = {
  304. "job_id": job_id,
  305. "code" : code,
  306. "data" : {
  307. "rcmd" : rcmd,
  308. "custom_details": custom_details
  309. },
  310. }
  311. print('ai_rcmd',json_info)
  312. try:
  313. # 下发分步指令
  314. url = 'http://m2-backend-svc:8000/api/ai/ai_rcmd_operation/add_ai_rcmd_operation_v3'
  315. r = requests.post(url,json=json_info,headers={'Content-Type': "application/json", "Connection": "close"})
  316. jsonResp = r.json()
  317. print(f'下发指令 jsonResp',jsonResp)
  318. except Exception as e:
  319. print(e)
  320. return