Compare commits

..

4 Commits

9 changed files with 72 additions and 52 deletions

View File

@@ -1,6 +1,6 @@
# TJWater Server 环境变量配置模板 # TJWater Server 环境变量配置模板
# 复制此文件为 .env 并填写实际值 # 复制此文件为 .env 并填写实际值
NETWORK_NAME="szh"
# ============================================ # ============================================
# 安全配置 (必填) # 安全配置 (必填)
# ============================================ # ============================================
@@ -16,20 +16,20 @@ ENCRYPTION_KEY=
# ============================================ # ============================================
# 数据库配置 (PostgreSQL) # 数据库配置 (PostgreSQL)
# ============================================ # ============================================
DB_NAME=tjwater DB_NAME="tjwater"
DB_HOST=localhost DB_HOST="localhost"
DB_PORT=5432 DB_PORT="5432"
DB_USER=postgres DB_USER="postgres"
DB_PASSWORD=password DB_PASSWORD="password"
# ============================================ # ============================================
# 数据库配置 (TimescaleDB) # 数据库配置 (TimescaleDB)
# ============================================ # ============================================
TIMESCALEDB_DB_NAME=szh TIMESCALEDB_DB_NAME="szh"
TIMESCALEDB_DB_HOST=localhost TIMESCALEDB_DB_HOST="localhost"
TIMESCALEDB_DB_PORT=5433 TIMESCALEDB_DB_PORT="5433"
TIMESCALEDB_DB_USER=tjwater TIMESCALEDB_DB_USER="tjwater"
TIMESCALEDB_DB_PASSWORD=Tjwater@123456 TIMESCALEDB_DB_PASSWORD="Tjwater@123456"
# ============================================ # ============================================
# InfluxDB 配置 (时序数据) # InfluxDB 配置 (时序数据)

13
.env.local Normal file
View File

@@ -0,0 +1,13 @@
NETWORK_NAME="szh"
DB_NAME="szh"
DB_HOST="192.168.1.114"
DB_PORT="5432"
DB_USER="tjwater"
DB_PASSWORD="Tjwater@123456"
TIMESCALEDB_DB_NAME="szh"
TIMESCALEDB_DB_HOST="192.168.1.114"
TIMESCALEDB_DB_PORT="5433"
TIMESCALEDB_DB_USER="tjwater"
TIMESCALEDB_DB_PASSWORD="Tjwater@123456"

View File

@@ -103,6 +103,7 @@ def burst_analysis(
if isinstance(burst_ID, list): if isinstance(burst_ID, list):
if (burst_size is not None) and (type(burst_size) is not list): if (burst_size is not None) and (type(burst_size) is not list):
return json.dumps("Type mismatch.") return json.dumps("Type mismatch.")
# 转化为列表形式
elif isinstance(burst_ID, str): elif isinstance(burst_ID, str):
burst_ID = [burst_ID] burst_ID = [burst_ID]
if burst_size is not None: if burst_size is not None:
@@ -344,18 +345,42 @@ def flushing_analysis(
# status['setting'] = 0.1036 * pow(valve_k, -3.105) # status['setting'] = 0.1036 * pow(valve_k, -3.105)
# cs.append(status) # cs.append(status)
# set_status(new_name,cs) # set_status(new_name,cs)
units = get_option(new_name) options = get_option(new_name)
units = options["UNITS"]
# step 2. set the emitter coefficient of drainage node or add flush flow to the drainage node # step 2. set the emitter coefficient of drainage node or add flush flow to the drainage node
# 新建 pattern
time_option = get_time(new_name)
hydraulic_step = time_option["HYDRAULIC TIMESTEP"]
secs = from_clock_to_seconds_2(hydraulic_step)
cs_pattern = ChangeSet()
pt = {}
factors = []
tmp_duration = modify_total_duration
while tmp_duration > 0:
factors.append(1.0)
tmp_duration = tmp_duration - secs
pt["id"] = "flushing_pt"
pt["factors"] = factors
cs_pattern.append(pt)
add_pattern(new_name, cs_pattern)
# 为 emitter_demand 添加新的 pattern
emitter_demand = get_demand(new_name, drainage_node_ID) emitter_demand = get_demand(new_name, drainage_node_ID)
cs = ChangeSet() cs = ChangeSet()
if flushing_flow > 0: if flushing_flow > 0:
for r in emitter_demand["demands"]: if units == "LPS":
if units == "LPS": emitter_demand["demands"].append(
r["demand"] += flushing_flow / 3.6 {
elif units == "CMH": "demand": flushing_flow / 3.6,
r["demand"] += flushing_flow "pattern": "flushing_pt",
cs.append(emitter_demand) "category": None,
set_demand(new_name, cs) }
)
elif units == "CMH":
emitter_demand["demands"].append(
{"demand": flushing_flow, "pattern": "flushing_pt", "category": None}
)
cs.append(emitter_demand)
set_demand(new_name, cs)
else: else:
pipes = get_node_links(new_name, drainage_node_ID) pipes = get_node_links(new_name, drainage_node_ID)
flush_diameter = 50 flush_diameter = 50

View File

@@ -196,10 +196,8 @@ async def burst_analysis_endpoint(
async def fastapi_burst_analysis( async def fastapi_burst_analysis(
network: str = Query(...), network: str = Query(...),
modify_pattern_start_time: str = Query(...), modify_pattern_start_time: str = Query(...),
burst_ID: list | str = Query(..., alias="burst_ID[]"), # 添加别名以匹配 URL burst_ID: list[str] = Query(...),
burst_size: list | float | int = Query( burst_size: list[float] = Query(...),
..., alias="burst_size[]"
), # 添加别名以匹配 URL
modify_total_duration: int = Query(...), modify_total_duration: int = Query(...),
scheme_name: str = Query(...), scheme_name: str = Query(...),
) -> str: ) -> str:

View File

@@ -1,22 +1,4 @@
import os import os
import yaml
# 获取当前项目根目录的路径 # 从环境变量 NETWORK_NAME 读取
_current_file = os.path.abspath(__file__) name = os.getenv("NETWORK_NAME")
project_root = os.path.dirname(os.path.dirname(os.path.dirname(_current_file)))
# 尝试读取 .yml 或 .yaml 文件
config_file = os.path.join(project_root, "configs", "project_info.yml")
if not os.path.exists(config_file):
config_file = os.path.join(project_root, "configs", "project_info.yaml")
if not os.path.exists(config_file):
raise FileNotFoundError(f"未找到项目配置文件 (project_info.yaml 或 .yml): {os.path.dirname(config_file)}")
with open(config_file, 'r', encoding='utf-8') as f:
_config = yaml.safe_load(f)
if not _config or 'name' not in _config:
raise KeyError(f"项目配置文件中缺少 'name' 配置: {config_file}")
name = _config['name']

View File

@@ -1190,12 +1190,12 @@ def run_simulation(
if modify_valve_opening[valve_name] == 0: if modify_valve_opening[valve_name] == 0:
valve_status["status"] = "CLOSED" valve_status["status"] = "CLOSED"
valve_status["setting"] = 0 valve_status["setting"] = 0
if modify_valve_opening[valve_name] < 1: elif modify_valve_opening[valve_name] < 1:
valve_status["status"] = "OPEN" valve_status["status"] = "OPEN"
valve_status["setting"] = 0.1036 * pow( valve_status["setting"] = 0.1036 * pow(
modify_valve_opening[valve_name], -3.105 modify_valve_opening[valve_name], -3.105
) )
if modify_valve_opening[valve_name] == 1: elif modify_valve_opening[valve_name] == 1:
valve_status["status"] = "OPEN" valve_status["status"] = "OPEN"
valve_status["setting"] = 0 valve_status["setting"] = 0
cs = ChangeSet() cs = ChangeSet()

View File

@@ -1 +0,0 @@
name: szh

View File

@@ -1,13 +1,19 @@
FROM python:3.12-slim FROM continuumio/miniconda3:latest
WORKDIR /app WORKDIR /app
# 安装 Python 3.12 和 pymetis (通过 conda-forge 避免编译问题)
RUN conda install -y -c conda-forge python=3.12 pymetis && \
conda clean -afy
COPY requirements.txt . COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt RUN pip install --no-cache-dir -r requirements.txt
COPY app ./app COPY app ./app
COPY resources ./resources COPY .env .
ENV PYTHONPATH=/app ENV PYTHONPATH=/app
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"] EXPOSE 8000
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"]

View File

@@ -95,7 +95,6 @@ prometheus_client==0.24.1
psycopg==3.2.5 psycopg==3.2.5
psycopg-binary==3.2.5 psycopg-binary==3.2.5
psycopg-pool==3.3.0 psycopg-pool==3.3.0
psycopg2==2.9.10
PuLP==3.1.1 PuLP==3.1.1
py-key-value-aio==0.3.0 py-key-value-aio==0.3.0
py-key-value-shared==0.3.0 py-key-value-shared==0.3.0
@@ -157,8 +156,6 @@ starlette==0.50.0
threadpoolctl==3.6.0 threadpoolctl==3.6.0
tqdm==4.67.1 tqdm==4.67.1
typer==0.21.1 typer==0.21.1
typing-inspection==0.4.0
typing_extensions==4.12.2
tzdata==2025.2 tzdata==2025.2
urllib3==2.2.3 urllib3==2.2.3
uvicorn==0.34.0 uvicorn==0.34.0