diff --git a/mcp/router.py b/mcp/router.py new file mode 100644 index 0000000..ef326cd --- /dev/null +++ b/mcp/router.py @@ -0,0 +1,152 @@ +from fastmcp import FastMCP, Context +from typing import Optional, Dict, Any + +from ..postgresql.database import get_database_instance +from ..postgresql.scada_info import ScadaRepository +from ..postgresql.scheme import SchemeRepository + +# 创建 MCP 服务器实例 +mcp = FastMCP("TJWater PostgreSQL Service", description="访问水务系统 PostgreSQL 数据库操作") + + +# 数据库连接辅助函数 +async def get_database_connection(db_name: Optional[str] = None, ctx: Context = None): + """获取数据库连接,支持通过参数指定数据库名称""" + if ctx: + await ctx.info(f"连接到数据库: {db_name or '默认数据库'}") + + instance = await get_database_instance(db_name) + async with instance.get_connection() as conn: + yield conn + + +@mcp.tool +async def get_scada_info(db_name: Optional[str] = None, ctx: Context = None) -> Dict[str, Any]: + """ + 查询所有 SCADA 信息 + + Args: + db_name: 可选的数据库名称,为空时使用默认数据库 + ctx: MCP 上下文,用于日志记录 + """ + try: + if ctx: + await ctx.info("查询 SCADA 信息...") + + async for conn in get_database_connection(db_name, ctx): + scada_data = await ScadaRepository.get_scadas(conn) + + if ctx: + await ctx.info(f"检索到 {len(scada_data)} 条 SCADA 记录") + + return {"success": True, "data": scada_data, "count": len(scada_data)} + except Exception as e: + error_msg = f"查询 SCADA 信息时发生错误: {str(e)}" + if ctx: + await ctx.error(error_msg) + return {"success": False, "error": error_msg} + + +@mcp.tool +async def get_scheme_list(db_name: Optional[str] = None, ctx: Context = None) -> Dict[str, Any]: + """ + 查询所有方案信息 + + Args: + db_name: 可选的数据库名称,为空时使用默认数据库 + ctx: MCP 上下文,用于日志记录 + """ + try: + if ctx: + await ctx.info("查询方案信息...") + + async for conn in get_database_connection(db_name, ctx): + scheme_data = await SchemeRepository.get_schemes(conn) + + if ctx: + await ctx.info(f"检索到 {len(scheme_data)} 条方案记录") + + return {"success": True, "data": scheme_data, "count": len(scheme_data)} + except Exception as e: + error_msg = f"查询方案信息时发生错误: {str(e)}" + if ctx: + await ctx.error(error_msg) + return {"success": False, "error": error_msg} + + +@mcp.tool +async def get_burst_locate_results(db_name: Optional[str] = None, ctx: Context = None) -> Dict[str, Any]: + """ + 查询所有爆管定位结果 + + Args: + db_name: 可选的数据库名称,为空时使用默认数据库 + ctx: MCP 上下文,用于日志记录 + """ + try: + if ctx: + await ctx.info("查询爆管定位结果...") + + async for conn in get_database_connection(db_name, ctx): + burst_data = await SchemeRepository.get_burst_locate_results(conn) + + if ctx: + await ctx.info(f"检索到 {len(burst_data)} 条爆管记录") + + return {"success": True, "data": burst_data, "count": len(burst_data)} + except Exception as e: + error_msg = f"查询爆管定位结果时发生错误: {str(e)}" + if ctx: + await ctx.error(error_msg) + return {"success": False, "error": error_msg} + + +@mcp.tool +async def get_burst_locate_result_by_incident( + burst_incident: str, + db_name: Optional[str] = None, + ctx: Context = None +) -> Dict[str, Any]: + """ + 根据 burst_incident 查询爆管定位结果 + + Args: + burst_incident: 爆管事件标识符 + db_name: 可选的数据库名称,为空时使用默认数据库 + ctx: MCP 上下文,用于日志记录 + """ + try: + if ctx: + await ctx.info(f"查询爆管事件 {burst_incident} 的结果...") + + async for conn in get_database_connection(db_name, ctx): + result = await SchemeRepository.get_burst_locate_result_by_incident( + conn, burst_incident + ) + + if ctx: + await ctx.info("检索到爆管事件数据") + + return result + except Exception as e: + error_msg = f"根据 burst_incident 查询爆管定位结果时发生错误: {str(e)}" + if ctx: + await ctx.error(error_msg) + return {"success": False, "error": error_msg} + + +# 添加静态配置资源 +@mcp.resource("config://database/supported_databases") +def get_supported_databases(): + """列出支持的数据库配置""" + return ["default", "backup", "analytics"] + + +@mcp.resource("config://api/version") +def get_api_version(): + """获取 API 版本""" + return "1.0.0" + + +if __name__ == "__main__": + mcp.run() \ No newline at end of file diff --git a/online_Analysis.py b/online_Analysis.py index 83d5240..c08b1c9 100644 --- a/online_Analysis.py +++ b/online_Analysis.py @@ -412,11 +412,11 @@ def flushing_analysis( ############################################################ def contaminant_simulation( name: str, - modify_pattern_start_time: str, - modify_total_duration: int = 900, - source: str = None, - concentration: float = None, - source_pattern: str = None, + 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 + source_pattern: str = None, # 污染源时间变化模式名称 scheme_Name: str = None, ) -> None: """ @@ -425,7 +425,7 @@ def contaminant_simulation( :param modify_pattern_start_time: 模拟开始时间,格式为'2024-11-25T09:00:00+08:00' :param modify_total_duration: 模拟总历时,秒 :param source: 污染源所在的节点ID - :param concentration: 污染源位置处的浓度,单位mg/L,即默认的污染模拟setting为concentration + :param concentration: 污染源位置处的浓度,单位mg/L,即默认的污染模拟setting为concentration(应改为 Set point booster) :param source_pattern: 污染源的时间变化模式,若不传入则默认以恒定浓度持续模拟,时间长度等于duration; 若传入,则格式为{1.0,0.5,1.1}等系数列表pattern_step模拟等于模型的hydraulic time step :param scheme_Name: 方案名称 diff --git a/requirements.txt b/requirements.txt index e47e5f0..7f52fa1 100644 Binary files a/requirements.txt and b/requirements.txt differ diff --git a/requirements2.txt b/requirements2.txt new file mode 100644 index 0000000..0700705 --- /dev/null +++ b/requirements2.txt @@ -0,0 +1,168 @@ +annotated-doc==0.0.4 +annotated-types==0.7.0 +anyio==4.8.0 +attrs==25.4.0 +Authlib==1.6.6 +beartype==0.22.9 +beautifulsoup4==4.13.4 +cachetools==6.2.4 +certifi==2024.8.30 +cffi==2.0.0 +chardet==5.2.0 +charset-normalizer==3.4.0 +click==8.1.8 +cloudpickle==3.1.2 +colorama==0.4.6 +contourpy==1.3.2 +cryptography==46.0.3 +cycler==0.12.1 +cyclopts==4.5.0 +Cython==3.0.12 +diskcache==5.6.3 +distro==1.9.0 +dnspython==2.8.0 +docstring_parser==0.17.0 +docutils==0.21.2 +dotenv==0.9.9 +ecos==2.0.14 +email-validator==2.3.0 +esda==2.7.0 +et_xmlfile==2.0.0 +exceptiongroup==1.3.1 +fakeredis==2.33.0 +fastapi==0.128.0 +fastmcp==2.9.2 +fonttools==4.58.0 +future==0.18.3 +GeoAlchemy2==0.17.1 +geopandas==1.0.1 +greenlet==3.1.1 +h11==0.14.0 +httpcore==1.0.7 +httpx==0.28.1 +httpx-sse==0.4.3 +idna==3.10 +importlib_metadata==8.7.1 +influxdb-client==1.48.0 +iniconfig==2.0.0 +jaraco.classes==3.4.0 +jaraco.context==6.1.0 +jaraco.functools==4.4.0 +jeepney==0.9.0 +Jinja2==3.1.6 +jiter==0.8.2 +joblib==1.5.0 +jsonschema==4.26.0 +jsonschema-path==0.3.4 +jsonschema-specifications==2025.9.1 +keyring==25.7.0 +Kivy==2.3.0 +Kivy-Garden==0.1.5 +kiwisolver==1.4.8 +libpysal==4.13.0 +lupa==2.6 +mapclassify==2.8.1 +markdown-it-py==3.0.0 +MarkupSafe==3.0.3 +matplotlib==3.10.3 +mcp==1.9.4 +mdurl==0.1.2 +more-itertools==10.8.0 +msgpack==1.1.0 +networkx==3.4.2 +numexpr==2.14.1 +numpy==1.26.2 +openai==1.63.0 +openapi-pydantic==0.5.1 +openpyxl==3.1.5 +opentelemetry-api==1.39.1 +opentelemetry-exporter-prometheus==0.60b1 +opentelemetry-instrumentation==0.60b1 +opentelemetry-sdk==1.39.1 +opentelemetry-semantic-conventions==0.60b1 +osqp==1.0.5 +packaging==25.0 +pandas==2.2.3 +pathable==0.4.4 +pathvalidate==3.3.1 +pillow==11.2.1 +pipdeptree==2.30.0 +platformdirs==4.3.8 +pluggy==1.5.0 +pointpats==2.5.1 +prometheus_client==0.24.1 +psycopg==3.2.5 +psycopg-binary==3.2.5 +psycopg-pool==3.3.0 +psycopg2==2.9.10 +PuLP==3.1.1 +py-key-value-aio==0.3.0 +py-key-value-shared==0.3.0 +py-linq==1.4.0 +pyarmor==9.0.7 +pyarmor.cli.core==7.6.4 +pybind11-stubgen==2.5.1 +pycparser==2.23 +pydantic==2.10.6 +pydantic-settings==2.12.0 +pydantic_core==2.27.2 +pydevd-pycharm==243.16718.36 +pydocket==0.16.6 +Pygments==2.18.0 +PyJWT==2.10.1 +pykalman==0.10.2 +# pymetis @ file:///D:/bld/pymetis_1762455149640/work 通过 conda 安装 pymetis,避免编译问题 conda install -c conda-forge pymetis +pynvim==0.5.0 +pyogrio==0.11.0 +pyparsing==3.2.3 +pyperclip==1.11.0 +pyproj==3.7.1 +pytest==8.3.5 +python-dateutil==2.9.0.post0 +python-dotenv==1.2.1 +python-json-logger==4.0.0 +python-multipart==0.0.20 +pytz==2025.2 +PyYAML==6.0.3 +pyzmq==26.2.1 +reactivex==4.0.4 +redis==5.2.1 +referencing==0.36.2 +requests==2.32.3 +rich==14.2.0 +rich-rst==1.3.2 +rpds-py==0.30.0 +rtree==1.4.0 +schedule==1.2.2 +scikit-base==0.12.6 +scikit-fuzzy==0.5.0 +scikit-learn==1.6.1 +scikit-survival==0.26.0 +scipy==1.15.2 +SecretStorage==3.5.0 +setuptools==80.7.1 +shapely==2.1.0 +shellingham==1.5.4 +six==1.17.0 +sniffio==1.3.1 +sortedcontainers==2.4.0 +soupsieve==2.7 +spaghetti==1.7.6 +spopt==0.6.1 +SQLAlchemy==2.0.41 +sse-starlette==3.0.4 +starlette==0.50.0 +threadpoolctl==3.6.0 +tqdm==4.67.1 +typer==0.21.1 +typing-inspection==0.4.0 +typing_extensions==4.12.2 +tzdata==2025.2 +urllib3==2.2.3 +uvicorn==0.34.0 +websockets==16.0 +wheel==0.45.1 +wntr==1.3.2 +wrapt==1.17.3 +zipp==3.23.0 +zmq==0.0.0