fix(simulation): align epanet output handling

This commit is contained in:
2026-06-11 10:29:04 +08:00
parent 21929b44fc
commit 67ba9c2ac6
5 changed files with 185 additions and 263 deletions
+20 -25
View File
@@ -27,15 +27,13 @@ import json
import pytz
import requests
import time
import shutil
from app.infra.epanet.epanet import Output
from typing import Optional, Tuple
import typing
import psycopg
import logging
import app.services.globals as globals
import uuid
import app.services.project_info as project_info
from app.services.time_api import parse_beijing_time
from app.core.config import get_pgconn_string
from app.infra.db.timescaledb.internal_queries import (
InternalQueries as TimescaleInternalQueries,
@@ -663,13 +661,14 @@ def from_seconds_to_clock(secs: int) -> str:
def convert_time_format(original_time: str) -> str:
"""
格式转换,将“2024-04-13T08:00:00+08:00"转为“2024-04-13 08:00:00
:param original_time: str “2024-04-13T08:00:00+08:00"格式的时间
格式转换,将带时区的 ISO 8601 / RFC3339 时间转为北京时间的“YYYY-MM-DD HH:MM:SS
:param original_time: str带显式时区的时间
:return: str,“2024-04-13 08:00:00”格式的时间
"""
new_time = original_time.replace("T", " ")
new_time = new_time.replace("+08:00", "")
return new_time
normalized_time = parse_beijing_time(
original_time, field_name="modify_pattern_start_time"
)
return normalized_time.replace(microsecond=0).strftime("%Y-%m-%d %H:%M:%S")
def get_history_pattern_info(project_name, pattern_name):
@@ -1218,7 +1217,7 @@ def run_simulation(
cs.append(valve_status)
set_status(name_c, cs)
# 运行并返回结果
run_project(name_c)
result_data = json.loads(run_project(name_c))
time_cost_end = time.perf_counter()
print(
"{} -- Hydraulic simulation finished, cost time: {:.2f} s.".format(
@@ -1226,23 +1225,22 @@ def run_simulation(
time_cost_end - time_cost_start,
)
)
# DingZQ 下面这几句一定要这样,不然读取不了
# time.sleep(5) # wait 5 seconds
# TODO: 2025/03/24
# DingZQ 这个名字要用随机数来处理
tmp_file = f"./temp/simulation_{uuid.uuid4()}.result.out"
shutil.copy(f"./temp/{name_c}.db.opt", tmp_file)
output = Output(tmp_file)
node_result = output.node_results()
link_result = output.link_results()
output_data = result_data.get("output")
if not isinstance(output_data, dict):
raise RuntimeError("run_project did not return JSON output content")
node_result = output_data.get("node_results")
link_result = output_data.get("link_results")
if node_result is None or link_result is None:
raise RuntimeError("run_project output missing node_results or link_results")
# link_flow = []
# for link in link_result:
# link_flow.append(link['result'][-1]['flow'])
# print(link_flow)
num_periods_result = output.times()["num_periods"]
times_info = output_data.get("times") or {}
num_periods_result = times_info.get("num_periods")
if num_periods_result is None:
raise RuntimeError("run_project output missing times.num_periods")
print("simulation_type", simulation_type)
print("before store result")
# print(num_periods_result)
@@ -1275,9 +1273,6 @@ def run_simulation(
print("after store result")
del output
os.remove(tmp_file)
if __name__ == "__main__":
# 计算前,获取scada_info中的信息,按照设定的方法修改pg数据库
+23 -16
View File
@@ -5,7 +5,6 @@ from math import pi
import pytz
from app.algorithms.simulation.runner import run_simulation_ex
from app.infra.epanet.epanet import Output
from app.services.tjnetwork import (
close_project,
copy_project,
@@ -110,10 +109,16 @@ def scheduling_simulation(
+ " -- Database Loading OK."
)
run_simulation_ex(
new_name, "realtime", start_time, duration=0, pump_control=pump_control
simulation_result = json.loads(
run_simulation_ex(
new_name, "realtime", start_time, duration=0, pump_control=pump_control
)
)
output_data = simulation_result.get("output")
if not isinstance(output_data, dict):
raise RuntimeError("run_simulation_ex did not return JSON output content")
if not is_project_open(new_name):
open_project(new_name)
@@ -131,18 +136,14 @@ def scheduling_simulation(
else:
tank_pipe_flow_direction[pipe_id] = -1
output = Output("./temp/{}.db.out".format(new_name))
node_results = (
output.node_results()
) # [{'node': str, 'result': [{'pressure': float}]}]
node_results = output_data.get("node_results") or [] # [{'node': str, 'result': [{'pressure': float}]}]
water_plant_output_pressure = 0
for node_result in node_results:
if node_result["node"] == water_plant_output_id: # 水厂出水压力(m)
water_plant_output_pressure = node_result["result"][-1]["pressure"]
water_plant_output_pressure /= 100 # 预计水厂出水压力(Mpa)
pipe_results = output.link_results() # [{'link': str, 'result': [{'flow': float}]}]
pipe_results = output_data.get("link_results") or [] # [{'link': str, 'result': [{'flow': float}]}]
tank_inflow = 0
for pipe_result in pipe_results:
for pipe_id in tank_pipes_id: # 遍历与水塔相连的管道
@@ -200,18 +201,24 @@ def daily_scheduling_simulation(
+ " -- Database Loading OK."
)
run_simulation_ex(
new_name, "realtime", start_time, duration=86400, pump_control=pump_control
simulation_result = json.loads(
run_simulation_ex(
new_name,
"realtime",
start_time,
duration=86400,
pump_control=pump_control,
)
)
output_data = simulation_result.get("output")
if not isinstance(output_data, dict):
raise RuntimeError("run_simulation_ex did not return JSON output content")
if not is_project_open(new_name):
open_project(new_name)
output = Output("./temp/{}.db.out".format(new_name))
node_results = (
output.node_results()
) # [{'node': str, 'result': [{'pressure': float, 'head': float}]}]
node_results = output_data.get("node_results") or [] # [{'node': str, 'result': [{'pressure': float, 'head': float}]}]
water_plant_output_pressure = []
reservoir_level = []
tank_level = []