调整epanet工具目录结构;联通前端水质分析模块功能;新建 readme.md
This commit is contained in:
@@ -1,4 +0,0 @@
|
||||
当前 适配 szh 项目的分支 是 dingsu/szh
|
||||
|
||||
Binary 适配的是 代码 中dingsu/szh 的部分
|
||||
当前只是把 API目录(也就是TJNetwork的部分)加密了
|
||||
@@ -5,7 +5,10 @@ from math import pi, sqrt
|
||||
import pytz
|
||||
|
||||
import app.services.simulation as simulation
|
||||
from app.algorithms.api_ex.run_simulation import run_simulation_ex, from_clock_to_seconds_2
|
||||
from app.algorithms.api_ex.run_simulation import (
|
||||
run_simulation_ex,
|
||||
from_clock_to_seconds_2,
|
||||
)
|
||||
from app.native.api.project import copy_project
|
||||
from app.services.epanet.epanet import Output
|
||||
from app.services.scheme_management import store_scheme_info
|
||||
@@ -43,7 +46,7 @@ def burst_analysis(
|
||||
modify_fixed_pump_pattern: dict[str, list] = None,
|
||||
modify_variable_pump_pattern: dict[str, list] = None,
|
||||
modify_valve_opening: dict[str, float] = None,
|
||||
scheme_Name: str = None,
|
||||
scheme_name: str = None,
|
||||
) -> None:
|
||||
"""
|
||||
爆管模拟
|
||||
@@ -55,7 +58,7 @@ def burst_analysis(
|
||||
:param modify_fixed_pump_pattern: dict中包含多个水泵模式,str为工频水泵的id,list为修改后的pattern
|
||||
:param modify_variable_pump_pattern: dict中包含多个水泵模式,str为变频水泵的id,list为修改后的pattern
|
||||
:param modify_valve_opening: dict中包含多个阀门开启度,str为阀门的id,float为修改后的阀门开启度
|
||||
:param scheme_Name: 方案名称
|
||||
:param scheme_name: 方案名称
|
||||
:return:
|
||||
"""
|
||||
scheme_detail: dict = {
|
||||
@@ -169,19 +172,19 @@ def burst_analysis(
|
||||
modify_fixed_pump_pattern=modify_fixed_pump_pattern,
|
||||
modify_variable_pump_pattern=modify_variable_pump_pattern,
|
||||
modify_valve_opening=modify_valve_opening,
|
||||
scheme_Type="burst_Analysis",
|
||||
scheme_Name=scheme_Name,
|
||||
scheme_type="burst_analysis",
|
||||
scheme_name=scheme_name,
|
||||
)
|
||||
# step 3. restore the base model status
|
||||
# execute_undo(name) #有疑惑
|
||||
if is_project_open(new_name):
|
||||
close_project(new_name)
|
||||
delete_project(new_name)
|
||||
# return result
|
||||
# 存储方案信息到 PG 数据库
|
||||
store_scheme_info(
|
||||
name=name,
|
||||
scheme_name=scheme_Name,
|
||||
scheme_type="burst_Analysis",
|
||||
scheme_name=scheme_name,
|
||||
scheme_type="burst_analysis",
|
||||
username="admin",
|
||||
scheme_start_time=modify_pattern_start_time,
|
||||
scheme_detail=scheme_detail,
|
||||
@@ -400,11 +403,11 @@ def flushing_analysis(
|
||||
def contaminant_simulation(
|
||||
name: str,
|
||||
modify_pattern_start_time: str, # 模拟开始时间,格式为'2024-11-25T09:00:00+08:00'
|
||||
modify_total_duration: int = 900, # 模拟总历时,秒
|
||||
source: str = None, # 污染源节点ID
|
||||
concentration: float = None, # 污染源浓度,单位mg/L
|
||||
modify_total_duration: int, # 模拟总历时,秒
|
||||
source: str, # 污染源节点ID
|
||||
concentration: float, # 污染源浓度,单位mg/L
|
||||
scheme_name: str = None,
|
||||
source_pattern: str = None, # 污染源时间变化模式名称
|
||||
scheme_Name: str = None,
|
||||
) -> None:
|
||||
"""
|
||||
污染模拟
|
||||
@@ -418,6 +421,12 @@ def contaminant_simulation(
|
||||
:param scheme_Name: 方案名称
|
||||
:return:
|
||||
"""
|
||||
scheme_detail: dict = {
|
||||
"source": source,
|
||||
"concentration": concentration,
|
||||
"duration": modify_total_duration,
|
||||
"pattern": source_pattern,
|
||||
}
|
||||
print(
|
||||
datetime.now(pytz.timezone("Asia/Shanghai")).strftime("%Y-%m-%d %H:%M:%S")
|
||||
+ " -- Start Analysis."
|
||||
@@ -520,8 +529,8 @@ def contaminant_simulation(
|
||||
simulation_type="extended",
|
||||
modify_pattern_start_time=modify_pattern_start_time,
|
||||
modify_total_duration=modify_total_duration,
|
||||
scheme_Type="contaminant_Analysis",
|
||||
scheme_Name=scheme_Name,
|
||||
scheme_type="contaminant_analysis",
|
||||
scheme_name=scheme_name,
|
||||
)
|
||||
|
||||
# for i in range(1,operation_step):
|
||||
@@ -529,7 +538,15 @@ def contaminant_simulation(
|
||||
if is_project_open(new_name):
|
||||
close_project(new_name)
|
||||
delete_project(new_name)
|
||||
# return result
|
||||
# 存储方案信息到 PG 数据库
|
||||
store_scheme_info(
|
||||
name=name,
|
||||
scheme_name=scheme_name,
|
||||
scheme_type="contaminant_analysis",
|
||||
username="admin",
|
||||
scheme_start_time=modify_pattern_start_time,
|
||||
scheme_detail=scheme_detail,
|
||||
)
|
||||
|
||||
|
||||
############################################################
|
||||
|
||||
@@ -192,19 +192,24 @@ async def burst_analysis_endpoint(
|
||||
return burst_analysis(network, pipe_id, start_time, end_time, burst_flow)
|
||||
|
||||
|
||||
@router.post("/burst_analysis/")
|
||||
async def fastapi_burst_analysis(data: BurstAnalysis) -> str:
|
||||
item = data.dict()
|
||||
@router.get("/burst_analysis/")
|
||||
async def fastapi_burst_analysis(
|
||||
network: str = Query(...),
|
||||
modify_pattern_start_time: str = Query(...),
|
||||
burst_ID: list | str = Query(..., alias="burst_ID[]"), # 添加别名以匹配 URL
|
||||
burst_size: list | float | int = Query(
|
||||
..., alias="burst_size[]"
|
||||
), # 添加别名以匹配 URL
|
||||
modify_total_duration: int = Query(...),
|
||||
scheme_name: str = Query(...),
|
||||
) -> str:
|
||||
burst_analysis(
|
||||
name=item["name"],
|
||||
modify_pattern_start_time=item["modify_pattern_start_time"],
|
||||
burst_ID=item["burst_ID"],
|
||||
burst_size=item["burst_size"],
|
||||
modify_total_duration=item["modify_total_duration"],
|
||||
modify_fixed_pump_pattern=item["modify_fixed_pump_pattern"],
|
||||
modify_variable_pump_pattern=item["modify_variable_pump_pattern"],
|
||||
modify_valve_opening=item["modify_valve_opening"],
|
||||
scheme_Name=item["scheme_Name"],
|
||||
name=network,
|
||||
modify_pattern_start_time=modify_pattern_start_time,
|
||||
burst_ID=burst_ID,
|
||||
burst_size=burst_size,
|
||||
modify_total_duration=modify_total_duration,
|
||||
scheme_name=scheme_name,
|
||||
)
|
||||
return "success"
|
||||
|
||||
@@ -254,7 +259,9 @@ async def fastapi_flushing_analysis(
|
||||
flush_flow: float = 0,
|
||||
duration: int | None = None,
|
||||
) -> str:
|
||||
valve_opening = {valve_id: float(valves_k[idx]) for idx, valve_id in enumerate(valves)}
|
||||
valve_opening = {
|
||||
valve_id: float(valves_k[idx]) for idx, valve_id in enumerate(valves)
|
||||
}
|
||||
result = flushing_analysis(
|
||||
name=network,
|
||||
modify_pattern_start_time=start_time,
|
||||
@@ -266,25 +273,20 @@ async def fastapi_flushing_analysis(
|
||||
return result or "success"
|
||||
|
||||
|
||||
@router.get("/contaminantsimulation/")
|
||||
async def contaminant_simulation_endpoint(
|
||||
network: str, node_id: str, start_time: str, duration: float, concentration: float
|
||||
):
|
||||
return contaminant_simulation(network, node_id, start_time, duration, concentration)
|
||||
|
||||
|
||||
@router.get("/contaminant_simulation/", response_class=PlainTextResponse)
|
||||
async def fastapi_contaminant_simulation(
|
||||
network: str,
|
||||
start_time: str,
|
||||
source: str,
|
||||
concentration: float,
|
||||
duration: int = 900,
|
||||
duration: int,
|
||||
scheme_name: str | None = None,
|
||||
pattern: str | None = None,
|
||||
) -> str:
|
||||
result = contaminant_simulation(
|
||||
name=network,
|
||||
modify_pattern_start_time=start_time,
|
||||
scheme_name=scheme_name,
|
||||
modify_total_duration=duration,
|
||||
source=source,
|
||||
concentration=concentration,
|
||||
@@ -431,9 +433,7 @@ async def fastapi_network_update(file: UploadFile = File()) -> str:
|
||||
async def fastapi_pump_failure(data: PumpFailureState) -> str:
|
||||
item = data.dict()
|
||||
with open("./pump_failure_message.txt", "a", encoding="utf-8-sig") as f1:
|
||||
f1.write(
|
||||
"[{}] {}\n".format(datetime.now().strftime("%Y-%m-%d %H:%M:%S"), item)
|
||||
)
|
||||
f1.write("[{}] {}\n".format(datetime.now().strftime("%Y-%m-%d %H:%M:%S"), item))
|
||||
with open("./pump_failure_status.txt", "r", encoding="utf-8-sig") as f2:
|
||||
lines = f2.readlines()
|
||||
first_stage_pump_status_dict = json.loads(json.dumps(eval(lines[0])))
|
||||
|
||||
@@ -56,4 +56,4 @@ app.add_middleware(GZipMiddleware, minimum_size=1000)
|
||||
# Include Routers
|
||||
app.include_router(api_router, prefix="/api/v1")
|
||||
# Legcy Routers without version prefix
|
||||
# app.include_router(api_router)
|
||||
app.include_router(api_router)
|
||||
|
||||
@@ -30,11 +30,11 @@ class Output:
|
||||
|
||||
if platform.system() == "Windows":
|
||||
self._lib = ctypes.CDLL(
|
||||
os.path.join(os.getcwd(), "epanet", "epanet-output.dll")
|
||||
os.path.join(os.path.dirname(__file__), "windows", "epanet-output.dll")
|
||||
)
|
||||
else:
|
||||
self._lib = ctypes.CDLL(
|
||||
os.path.join(os.getcwd(), "epanet", "linux", "libepanet-output.so")
|
||||
os.path.join(os.path.dirname(__file__), "linux", "libepanet-output.so")
|
||||
)
|
||||
|
||||
self._handle = ctypes.c_void_p()
|
||||
@@ -314,9 +314,9 @@ def run_project_return_dict(name: str, readable_output: bool = False) -> dict[st
|
||||
|
||||
input = name + ".db"
|
||||
if platform.system() == "Windows":
|
||||
exe = os.path.join(os.path.join(dir, "epanet"), "runepanet.exe")
|
||||
exe = os.path.join(os.path.dirname(__file__), "windows", "runepanet.exe")
|
||||
else:
|
||||
exe = os.path.join(os.path.join(dir, "epanet"), "linux", "runepanet")
|
||||
exe = os.path.join(os.path.dirname(__file__), "linux", "runepanet")
|
||||
inp = os.path.join(os.path.join(dir, "db_inp"), input + ".inp")
|
||||
rpt = os.path.join(os.path.join(dir, "temp"), input + ".rpt")
|
||||
opt = os.path.join(os.path.join(dir, "temp"), input + ".opt")
|
||||
@@ -364,9 +364,9 @@ def run_project(name: str, readable_output: bool = False) -> str:
|
||||
|
||||
input = name + ".db"
|
||||
if platform.system() == "Windows":
|
||||
exe = os.path.join(os.path.join(dir, "epanet"), "runepanet.exe")
|
||||
exe = os.path.join(os.path.dirname(__file__), "windows", "runepanet.exe")
|
||||
else:
|
||||
exe = os.path.join(os.path.join(dir, "epanet"), "linux", "runepanet")
|
||||
exe = os.path.join(os.path.dirname(__file__), "linux", "runepanet")
|
||||
inp = os.path.join(os.path.join(dir, "db_inp"), input + ".inp")
|
||||
rpt = os.path.join(os.path.join(dir, "temp"), input + ".rpt")
|
||||
opt = os.path.join(os.path.join(dir, "temp"), input + ".opt")
|
||||
@@ -416,9 +416,9 @@ def run_inp(name: str) -> str:
|
||||
dir = os.path.abspath(os.getcwd())
|
||||
|
||||
if platform.system() == "Windows":
|
||||
exe = os.path.join(os.path.join(dir, "epanet"), "runepanet.exe")
|
||||
exe = os.path.join(os.path.dirname(__file__), "windows", "runepanet.exe")
|
||||
else:
|
||||
exe = os.path.join(os.path.join(dir, "epanet"), "linux", "runepanet")
|
||||
exe = os.path.join(os.path.dirname(__file__), "linux", "runepanet")
|
||||
inp = os.path.join(os.path.join(dir, "inp"), name + ".inp")
|
||||
rpt = os.path.join(os.path.join(dir, "temp"), name + ".rpt")
|
||||
opt = os.path.join(os.path.join(dir, "temp"), name + ".opt")
|
||||
|
||||
@@ -21,8 +21,12 @@ import app.services.globals as globals
|
||||
import uuid
|
||||
import app.services.project_info as project_info
|
||||
from app.native.api.postgresql_info import get_pgconn_string
|
||||
from app.infra.db.timescaledb.internal_queries import InternalQueries as TimescaleInternalQueries
|
||||
from app.infra.db.timescaledb.internal_queries import InternalStorage as TimescaleInternalStorage
|
||||
from app.infra.db.timescaledb.internal_queries import (
|
||||
InternalQueries as TimescaleInternalQueries,
|
||||
)
|
||||
from app.infra.db.timescaledb.internal_queries import (
|
||||
InternalStorage as TimescaleInternalStorage,
|
||||
)
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
|
||||
@@ -679,8 +683,8 @@ def run_simulation(
|
||||
modify_fixed_pump_pattern: dict[str, list] = None,
|
||||
modify_variable_pump_pattern: dict[str, list] = None,
|
||||
modify_valve_opening: dict[str, float] = None,
|
||||
scheme_Type: str = None,
|
||||
scheme_Name: str = None,
|
||||
scheme_type: str = None,
|
||||
scheme_name: str = None,
|
||||
) -> None:
|
||||
"""
|
||||
传入需要修改的参数,改变数据库中对应位置的值,然后计算,返回结果
|
||||
@@ -695,8 +699,8 @@ def run_simulation(
|
||||
:param modify_fixed_pump_pattern: dict中包含多个水泵模式,str为工频水泵的id,list为修改后的pattern
|
||||
:param modify_variable_pump_pattern: dict中包含多个水泵模式,str为变频水泵的id,list为修改后的pattern
|
||||
:param modify_valve_opening: dict中包含多个阀门开启度,str为阀门的id,float为修改后的阀门开启度
|
||||
:param scheme_Type: 模拟方案类型
|
||||
:param scheme_Name:模拟方案名称
|
||||
:param scheme_type: 模拟方案类型
|
||||
:param scheme_name:模拟方案名称
|
||||
:return:
|
||||
"""
|
||||
# 记录开始时间
|
||||
@@ -1235,8 +1239,8 @@ def run_simulation(
|
||||
)
|
||||
elif simulation_type.upper() == "EXTENDED":
|
||||
TimescaleInternalStorage.store_scheme_simulation(
|
||||
scheme_Type,
|
||||
scheme_Name,
|
||||
scheme_type,
|
||||
scheme_name,
|
||||
node_result,
|
||||
link_result,
|
||||
modify_pattern_start_time,
|
||||
|
||||
41
readme.md
Normal file
41
readme.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# TJWater Server (FastAPI)
|
||||
|
||||
基于 FastAPI 的水务业务服务端,提供模拟计算、SCADA 数据、网络元素、项目管理等接口。
|
||||
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
app/
|
||||
main.py # FastAPI 入口(lifespan、CORS、路由挂载)
|
||||
api/
|
||||
v1/
|
||||
router.py # API 路由汇总(/api/v1 前缀)
|
||||
endpoints/ # 业务接口实现(auth、simulation、scada 等)
|
||||
endpoints/network/ # 管网要素与特性接口
|
||||
endpoints/components/ # 组件/控制相关接口
|
||||
services/ # 业务服务层(simulation、tjnetwork 等)
|
||||
infra/
|
||||
db/ # 数据库访问层(timescaledb / postgresql / influxdb)
|
||||
cache/ # 缓存与 Redis 客户端
|
||||
algorithms/ # 算法与分析模块
|
||||
core/ # 配置与安全相关
|
||||
configs/
|
||||
project_info.yml # 默认工程配置(启动时自动打开)
|
||||
scripts/
|
||||
run_server.py # Uvicorn 启动脚本
|
||||
tests/ # 测试
|
||||
```
|
||||
|
||||
## 启动方式
|
||||
|
||||
1. 安装依赖(示例):
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
2. 启动服务:
|
||||
```bash
|
||||
python scripts/run_server.py
|
||||
```
|
||||
|
||||
默认监听:`http://0.0.0.0:8000`
|
||||
API 前缀:`/api/v1`(见 `app/main.py` 与 `app/api/v1/router.py`)
|
||||
@@ -3710,8 +3710,9 @@ async def fastapi_contaminant_simulation(
|
||||
start_time: str,
|
||||
source: str,
|
||||
concentration: float,
|
||||
duration: int = 900,
|
||||
duration: int,
|
||||
pattern: str = None,
|
||||
scheme_Name: str = None,
|
||||
) -> str:
|
||||
filename = "c:/lock.simulation"
|
||||
filename2 = "c:/lock.simulation2"
|
||||
|
||||
@@ -56,7 +56,7 @@ def burst_analysis(
|
||||
modify_fixed_pump_pattern: dict[str, list] = None,
|
||||
modify_variable_pump_pattern: dict[str, list] = None,
|
||||
modify_valve_opening: dict[str, float] = None,
|
||||
scheme_Name: str = None,
|
||||
scheme_name: str = None,
|
||||
) -> None:
|
||||
"""
|
||||
爆管模拟
|
||||
@@ -182,8 +182,8 @@ def burst_analysis(
|
||||
modify_fixed_pump_pattern=modify_fixed_pump_pattern,
|
||||
modify_variable_pump_pattern=modify_variable_pump_pattern,
|
||||
modify_valve_opening=modify_valve_opening,
|
||||
scheme_Type="burst_Analysis",
|
||||
scheme_Name=scheme_Name,
|
||||
scheme_type="burst_Analysis",
|
||||
scheme_name=scheme_name,
|
||||
)
|
||||
# step 3. restore the base model status
|
||||
# execute_undo(name) #有疑惑
|
||||
@@ -193,7 +193,7 @@ def burst_analysis(
|
||||
# return result
|
||||
store_scheme_info(
|
||||
name=name,
|
||||
scheme_name=scheme_Name,
|
||||
scheme_name=scheme_name,
|
||||
scheme_type="burst_Analysis",
|
||||
username="admin",
|
||||
scheme_start_time=modify_pattern_start_time,
|
||||
@@ -209,7 +209,7 @@ def valve_close_analysis(
|
||||
modify_pattern_start_time: str,
|
||||
modify_total_duration: int = 900,
|
||||
modify_valve_opening: dict[str, float] = None,
|
||||
scheme_Name: str = None,
|
||||
scheme_name: str = None,
|
||||
) -> None:
|
||||
"""
|
||||
关阀模拟
|
||||
@@ -217,7 +217,7 @@ def valve_close_analysis(
|
||||
:param modify_pattern_start_time: 模拟开始时间,格式为'2024-11-25T09:00:00+08:00'
|
||||
:param modify_total_duration: 模拟总历时,秒
|
||||
:param modify_valve_opening: dict中包含多个阀门开启度,str为阀门的id,float为修改后的阀门开启度
|
||||
:param scheme_Name: 方案名称
|
||||
:param scheme_name: 方案名称
|
||||
:return:
|
||||
"""
|
||||
print(
|
||||
@@ -271,8 +271,8 @@ def valve_close_analysis(
|
||||
modify_pattern_start_time=modify_pattern_start_time,
|
||||
modify_total_duration=modify_total_duration,
|
||||
modify_valve_opening=modify_valve_opening,
|
||||
scheme_Type="valve_close_Analysis",
|
||||
scheme_Name=scheme_Name,
|
||||
scheme_type="valve_close_Analysis",
|
||||
scheme_name=scheme_name,
|
||||
)
|
||||
# step 3. restore the base model
|
||||
# for valve in valves:
|
||||
|
||||
Reference in New Issue
Block a user