627 lines
33 KiB
Python
627 lines
33 KiB
Python
from __future__ import annotations
|
||
|
||
from .core import CommandDoc, CommandOptionDoc, SCHEMA_VERSION
|
||
|
||
GROUP_SUMMARIES: dict[tuple[str, ...], str] = {
|
||
("network",): "管网节点、管线等基础属性查询命令。",
|
||
("component",): "组件选项与配置读取命令。",
|
||
("component", "option"): "组件选项查询命令。",
|
||
("simulation",): "模拟运行与调度相关命令。",
|
||
("analysis",): "分析计算与诊断相关命令。",
|
||
("analysis", "leakage"): "漏损分析相关命令。",
|
||
("analysis", "leakage", "schemes"): "漏损方案查询命令。",
|
||
("analysis", "burst-detection"): "爆管检测相关命令。",
|
||
("analysis", "burst-detection", "schemes"): "爆管检测方案查询命令。",
|
||
("analysis", "burst-location"): "爆管定位相关命令。",
|
||
("analysis", "burst-location", "schemes"): "爆管定位方案查询命令。",
|
||
("analysis", "risk"): "风险分析相关命令。",
|
||
("analysis", "sensor-placement"): "传感器选址相关命令。",
|
||
("data",): "时序、SCADA 和方案数据查询命令。",
|
||
("data", "timeseries"): "时序数据查询命令。",
|
||
("data", "timeseries", "realtime"): "实时模拟时序查询命令。",
|
||
("data", "timeseries", "scheme"): "方案时序查询命令。",
|
||
("data", "timeseries", "scada"): "SCADA 时序查询命令。",
|
||
("data", "timeseries", "composite"): "复合时序查询命令。",
|
||
("data", "scada"): "SCADA 元数据查询命令。",
|
||
("data", "scheme"): "方案数据查询命令。",
|
||
}
|
||
|
||
HIDDEN_PATH_PREFIXES: tuple[tuple[str, ...], ...] = (
|
||
("analysis", "burst-location"),
|
||
("analysis", "risk"),
|
||
)
|
||
|
||
COMMAND_DOCS: dict[tuple[str, ...], CommandDoc] = {
|
||
("network", "get-junction-properties"): CommandDoc(
|
||
path=("network", "get-junction-properties"),
|
||
summary="读取节点属性",
|
||
description="调用 /getjunctionproperties/。",
|
||
options=(CommandOptionDoc("junction", "节点 ID", required=True),),
|
||
examples=("tjwater-cli network get-junction-properties --junction J1",),
|
||
),
|
||
("network", "get-pipe-properties"): CommandDoc(
|
||
path=("network", "get-pipe-properties"),
|
||
summary="读取管道属性",
|
||
description="调用 /getpipeproperties/。",
|
||
options=(CommandOptionDoc("pipe", "管道 ID", required=True),),
|
||
examples=("tjwater-cli network get-pipe-properties --pipe P1",),
|
||
),
|
||
("network", "get-all-pipes-properties"): CommandDoc(
|
||
path=("network", "get-all-pipes-properties"),
|
||
summary="读取全部管道属性",
|
||
description="调用 /getallpipeproperties/。",
|
||
examples=("tjwater-cli network get-all-pipes-properties",),
|
||
),
|
||
("network", "get-reservoir-properties"): CommandDoc(
|
||
path=("network", "get-reservoir-properties"),
|
||
summary="读取水库属性",
|
||
description="调用 /getreservoirproperties/。",
|
||
options=(CommandOptionDoc("reservoir", "水库 ID", required=True),),
|
||
examples=("tjwater-cli network get-reservoir-properties --reservoir R1",),
|
||
),
|
||
("network", "get-all-reservoirs-properties"): CommandDoc(
|
||
path=("network", "get-all-reservoirs-properties"),
|
||
summary="读取全部水库属性",
|
||
description="调用 /getallreservoirproperties/。",
|
||
examples=("tjwater-cli network get-all-reservoirs-properties",),
|
||
),
|
||
("network", "get-tank-properties"): CommandDoc(
|
||
path=("network", "get-tank-properties"),
|
||
summary="读取水箱属性",
|
||
description="调用 /gettankproperties/。",
|
||
options=(CommandOptionDoc("tank", "水箱 ID", required=True),),
|
||
examples=("tjwater-cli network get-tank-properties --tank T1",),
|
||
),
|
||
("network", "get-all-tanks-properties"): CommandDoc(
|
||
path=("network", "get-all-tanks-properties"),
|
||
summary="读取全部水箱属性",
|
||
description="调用 /getalltankproperties/。",
|
||
examples=("tjwater-cli network get-all-tanks-properties",),
|
||
),
|
||
("network", "get-pump-properties"): CommandDoc(
|
||
path=("network", "get-pump-properties"),
|
||
summary="读取水泵属性",
|
||
description="调用 /getpumpproperties/。",
|
||
options=(CommandOptionDoc("pump", "水泵 ID", required=True),),
|
||
examples=("tjwater-cli network get-pump-properties --pump PU1",),
|
||
),
|
||
("network", "get-all-pumps-properties"): CommandDoc(
|
||
path=("network", "get-all-pumps-properties"),
|
||
summary="读取全部水泵属性",
|
||
description="调用 /getallpumpproperties/。",
|
||
examples=("tjwater-cli network get-all-pumps-properties",),
|
||
),
|
||
("network", "get-valve-properties"): CommandDoc(
|
||
path=("network", "get-valve-properties"),
|
||
summary="读取阀门属性",
|
||
description="调用 /getvalveproperties/。",
|
||
options=(CommandOptionDoc("valve", "阀门 ID", required=True),),
|
||
examples=("tjwater-cli network get-valve-properties --valve V1",),
|
||
),
|
||
("network", "get-all-valves-properties"): CommandDoc(
|
||
path=("network", "get-all-valves-properties"),
|
||
summary="读取全部阀门属性",
|
||
description="调用 /getallvalveproperties/。",
|
||
examples=("tjwater-cli network get-all-valves-properties",),
|
||
),
|
||
("component", "option", "schema"): CommandDoc(
|
||
path=("component", "option", "schema"),
|
||
summary="读取选项 schema",
|
||
description="kind 支持 time、energy、pump-energy、network。",
|
||
options=(
|
||
CommandOptionDoc("kind", "选项类型", required=True),
|
||
CommandOptionDoc("pump", "pump-energy 时需要的泵 ID"),
|
||
),
|
||
examples=(
|
||
"tjwater-cli component option schema --kind time",
|
||
"tjwater-cli component option schema --kind energy",
|
||
"tjwater-cli component option schema --kind pump-energy --pump PUMP1",
|
||
"tjwater-cli component option schema --kind network",
|
||
),
|
||
),
|
||
("component", "option", "get"): CommandDoc(
|
||
path=("component", "option", "get"),
|
||
summary="读取选项属性",
|
||
description="kind 支持 time、energy、pump-energy、network。",
|
||
options=(
|
||
CommandOptionDoc("kind", "选项类型", required=True),
|
||
CommandOptionDoc("pump", "pump-energy 时需要的泵 ID"),
|
||
),
|
||
examples=(
|
||
"tjwater-cli component option get --kind time",
|
||
"tjwater-cli component option get --kind energy",
|
||
"tjwater-cli component option get --kind pump-energy --pump PUMP1",
|
||
"tjwater-cli component option get --kind network",
|
||
),
|
||
),
|
||
("simulation", "run"): CommandDoc(
|
||
path=("simulation", "run"),
|
||
summary="触发指定绝对时间的模拟运行",
|
||
description="把显式带时区的 RFC3339 start-time 直接传给 /runsimulationmanuallybydate/;服务端按带时区时间处理并统一按 UTC 存储结果,实时数据需后续通过 data timeseries 在对应时间段查询。duration 单位为分钟。",
|
||
options=(
|
||
CommandOptionDoc("start-time", "显式带时区的开始时间", required=True),
|
||
CommandOptionDoc("duration", "持续分钟数", required=True),
|
||
),
|
||
examples=("tjwater-cli simulation run --start-time 2025-01-02T03:04:05+08:00 --duration 30",),
|
||
next_commands=(
|
||
"tjwater-cli data timeseries realtime links --start-time 2025-01-02T03:04:05+08:00 --end-time 2025-01-02T03:34:05+08:00",
|
||
"tjwater-cli data timeseries realtime nodes --start-time 2025-01-02T03:04:05+08:00 --end-time 2025-01-02T03:34:05+08:00",
|
||
),
|
||
output="模拟触发结果;实时数据需通过 data timeseries 命令按时间段查询",
|
||
),
|
||
("analysis", "burst"): CommandDoc(
|
||
path=("analysis", "burst"),
|
||
summary="执行爆管分析",
|
||
description="读取 burst-file 并转换为 burst_ID[] / burst_size[];接口本身只返回分析执行结果,方案数据需后续通过 data scheme 命令获取。duration 单位为秒。",
|
||
options=(
|
||
CommandOptionDoc("start-time", "显式带时区的开始时间", required=True),
|
||
CommandOptionDoc("duration", "持续秒数", required=True),
|
||
CommandOptionDoc("burst-file", "爆管输入 JSON 文件", required=True),
|
||
CommandOptionDoc("scheme", "方案名称"),
|
||
),
|
||
examples=(
|
||
"tjwater-cli analysis burst --start-time 2025-01-02T03:04:05+08:00 --duration 900 --burst-file ./burst.json --scheme burst_case_01",
|
||
"tjwater-cli data scheme get --name burst_case_01",
|
||
"tjwater-cli data scheme list",
|
||
),
|
||
),
|
||
("analysis", "valve"): CommandDoc(
|
||
path=("analysis", "valve"),
|
||
summary="阀门工况分析。",
|
||
description="close 模式按指定阀门关闭执行定时长模拟;isolation 模式按指定事故元素计算关阀隔离方案。duration 单位为秒。",
|
||
options=(
|
||
CommandOptionDoc(name="mode", description="阀门操作模式:'close' 或 'isolation'", required=True),
|
||
CommandOptionDoc(name="start-time", description="close 模式需要的起始绝对时间,必须显式带时区偏移"),
|
||
CommandOptionDoc(name="valve", description="close 模式下需关闭的阀门 ID(可多次指定)", repeated=True),
|
||
CommandOptionDoc(name="element", description="isolation 模式下的事故元素 ID(可多次指定)", repeated=True),
|
||
CommandOptionDoc(name="disabled-valve", description="isolation 模式下需排除的故障阀门 ID(可多次指定)", repeated=True),
|
||
CommandOptionDoc(name="duration", description="close 模式持续秒数,默认 900"),
|
||
CommandOptionDoc(name="scheme", description="close 模式方案名称"),
|
||
),
|
||
examples=(
|
||
"tjwater-cli analysis valve --mode close --start-time 2025-01-02T03:04:05+08:00 --valve V1 --valve V2 --duration 900 --scheme valve_case_01",
|
||
"tjwater-cli analysis valve --mode isolation --element E1 --element E2",
|
||
"tjwater-cli analysis valve --mode isolation --element E1 --disabled-valve V3",
|
||
),
|
||
),
|
||
("analysis", "flushing"): CommandDoc(
|
||
path=("analysis", "flushing"),
|
||
summary="执行冲洗分析",
|
||
description="读取 valve-setting-file 并转换为 valves[] / valves_k[]。duration 单位为秒,默认 900。",
|
||
options=(
|
||
CommandOptionDoc("start-time", "显式带时区的开始时间", required=True),
|
||
CommandOptionDoc("valve-setting-file", "阀门开度 JSON 文件", required=True),
|
||
CommandOptionDoc("drainage-node", "排污节点 ID", required=True),
|
||
CommandOptionDoc("flow", "冲洗流量", required=True),
|
||
CommandOptionDoc("duration", "持续秒数,默认 900"),
|
||
CommandOptionDoc("scheme", "方案名称", required=True),
|
||
),
|
||
examples=("tjwater-cli analysis flushing --start-time 2025-01-02T03:04:05+08:00 --valve-setting-file ./valve.json --drainage-node N1 --flow 100.0 --duration 900 --scheme flush_case_01",),
|
||
),
|
||
("analysis", "age"): CommandDoc(
|
||
path=("analysis", "age"),
|
||
summary="执行水龄分析",
|
||
description="调用 /age_analysis/。duration 单位为秒。",
|
||
options=(
|
||
CommandOptionDoc("start-time", "显式带时区的开始时间", required=True),
|
||
CommandOptionDoc("duration", "持续秒数", required=True),
|
||
),
|
||
examples=("tjwater-cli analysis age --start-time 2025-01-02T03:04:05+08:00 --duration 900",),
|
||
),
|
||
("analysis", "contaminant"): CommandDoc(
|
||
path=("analysis", "contaminant"),
|
||
summary="执行污染物模拟",
|
||
description="调用 /contaminant_simulation/。duration 单位为秒。",
|
||
options=(
|
||
CommandOptionDoc("start-time", "显式带时区的开始时间", required=True),
|
||
CommandOptionDoc("duration", "持续秒数", required=True),
|
||
CommandOptionDoc("source-node", "污染源节点 ID", required=True),
|
||
CommandOptionDoc("concentration", "浓度值", required=True),
|
||
CommandOptionDoc("pattern", "模式 ID"),
|
||
CommandOptionDoc("scheme", "方案名称", required=True),
|
||
),
|
||
examples=("tjwater-cli analysis contaminant --start-time 2025-01-02T03:04:05+08:00 --duration 900 --source-node N1 --concentration 10.0 --scheme contam_case_01",),
|
||
),
|
||
("analysis", "sensor-placement", "kmeans"): CommandDoc(
|
||
path=("analysis", "sensor-placement", "kmeans"),
|
||
summary="执行 KMeans 传感器选址",
|
||
description="使用 POST /pressure_sensor_placement_kmeans/,补齐 username 和 min_diameter。",
|
||
options=(
|
||
CommandOptionDoc("count", "传感器数量", required=True),
|
||
CommandOptionDoc("min-diameter", "最小管径,默认 0"),
|
||
CommandOptionDoc("scheme", "方案名称"),
|
||
),
|
||
examples=("tjwater-cli analysis sensor-placement kmeans --count 5 --min-diameter 100 --scheme placement_case_01",),
|
||
),
|
||
("analysis", "leakage", "identify"): CommandDoc(
|
||
path=("analysis", "leakage", "identify"),
|
||
summary="执行漏损识别",
|
||
description="把 CLI 时间映射到 scada_start / scada_end。",
|
||
options=(
|
||
CommandOptionDoc("start-time", "显式带时区的 SCADA 开始时间", required=True),
|
||
CommandOptionDoc("end-time", "显式带时区的 SCADA 结束时间", required=True),
|
||
CommandOptionDoc("scheme", "方案名称"),
|
||
),
|
||
examples=("tjwater-cli analysis leakage identify --start-time 2025-01-02T03:00:00+08:00 --end-time 2025-01-02T04:00:00+08:00 --scheme leak_case_01",),
|
||
),
|
||
("analysis", "leakage", "schemes", "list"): CommandDoc(
|
||
path=("analysis", "leakage", "schemes", "list"),
|
||
summary="列出漏损方案",
|
||
description="调用 /leakage/schemes/。",
|
||
examples=("tjwater-cli analysis leakage schemes list",),
|
||
),
|
||
("analysis", "leakage", "schemes", "get"): CommandDoc(
|
||
path=("analysis", "leakage", "schemes", "get"),
|
||
summary="读取漏损方案详情",
|
||
description="调用 /leakage/schemes/{scheme_name}。",
|
||
examples=("tjwater-cli analysis leakage schemes get my_scheme",),
|
||
),
|
||
("analysis", "burst-detection", "detect"): CommandDoc(
|
||
path=("analysis", "burst-detection", "detect"),
|
||
summary="执行爆管检测",
|
||
description="调用 /burst-detection/detect/。",
|
||
options=(
|
||
CommandOptionDoc("start-time", "显式带时区的 SCADA 开始时间", required=True),
|
||
CommandOptionDoc("end-time", "显式带时区的 SCADA 结束时间", required=True),
|
||
CommandOptionDoc("scheme", "方案名称"),
|
||
),
|
||
examples=("tjwater-cli analysis burst-detection detect --start-time 2025-01-02T03:00:00+08:00 --end-time 2025-01-02T04:00:00+08:00 --scheme detect_case_01",),
|
||
),
|
||
("analysis", "burst-detection", "schemes", "list"): CommandDoc(
|
||
path=("analysis", "burst-detection", "schemes", "list"),
|
||
summary="列出爆管检测方案",
|
||
description="调用 /burst-detection/schemes/。",
|
||
examples=("tjwater-cli analysis burst-detection schemes list",),
|
||
),
|
||
("analysis", "burst-detection", "schemes", "get"): CommandDoc(
|
||
path=("analysis", "burst-detection", "schemes", "get"),
|
||
summary="读取爆管检测方案详情",
|
||
description="调用 /burst-detection/schemes/{scheme_name}。",
|
||
examples=("tjwater-cli analysis burst-detection schemes get my_scheme",),
|
||
),
|
||
("analysis", "burst-location", "locate"): CommandDoc(
|
||
path=("analysis", "burst-location", "locate"),
|
||
summary="执行爆管定位",
|
||
description="调用 /burst-location/locate/;需要 burst-leakage。支持 monitoring 和 simulation 两种数据源。",
|
||
options=(
|
||
CommandOptionDoc("start-time", "显式带时区的 SCADA 开始时间", required=True),
|
||
CommandOptionDoc("end-time", "显式带时区的 SCADA 结束时间", required=True),
|
||
CommandOptionDoc("burst-leakage", "爆管漏水量", required=True),
|
||
CommandOptionDoc("scheme", "方案名称"),
|
||
CommandOptionDoc("data-source", "数据源:monitoring(默认)或 simulation"),
|
||
CommandOptionDoc("pressure-scada-id", "压力 SCADA ID(可多次指定)", repeated=True),
|
||
CommandOptionDoc("flow-scada-id", "流量 SCADA ID(可多次指定)", repeated=True),
|
||
CommandOptionDoc("pressure-file", "包含 burst_pressure/normal_pressure 的 JSON 文件"),
|
||
CommandOptionDoc("flow-file", "包含 burst_flow/normal_flow 的 JSON 文件"),
|
||
CommandOptionDoc("use-scada-flow", "启用 SCADA 流量"),
|
||
),
|
||
examples=(
|
||
"tjwater-cli analysis burst-location locate --start-time 2025-01-02T03:00:00+08:00 --end-time 2025-01-02T04:00:00+08:00 --burst-leakage 100.0 --scheme locate_case_01",
|
||
"tjwater-cli analysis burst-location locate --start-time 2025-01-02T03:00:00+08:00 --end-time 2025-01-02T04:00:00+08:00 --burst-leakage 50.0 --scheme locate_case_01 --data-source simulation --pressure-file ./pressure.json --flow-file ./flow.json",
|
||
),
|
||
),
|
||
("analysis", "burst-location", "schemes", "list"): CommandDoc(
|
||
path=("analysis", "burst-location", "schemes", "list"),
|
||
summary="列出爆管定位方案",
|
||
description="调用 /burst-location/schemes/。",
|
||
examples=("tjwater-cli analysis burst-location schemes list",),
|
||
),
|
||
("analysis", "burst-location", "schemes", "get"): CommandDoc(
|
||
path=("analysis", "burst-location", "schemes", "get"),
|
||
summary="读取爆管定位方案详情",
|
||
description="调用 /burst-location/schemes/{scheme_name}。",
|
||
examples=("tjwater-cli analysis burst-location schemes get my_scheme",),
|
||
),
|
||
("analysis", "risk", "pipe-now"): CommandDoc(
|
||
path=("analysis", "risk", "pipe-now"),
|
||
summary="读取单条管道当前风险",
|
||
description="调用 /getpiperiskprobabilitynow/。",
|
||
options=(CommandOptionDoc("pipe", "管道 ID", required=True),),
|
||
examples=("tjwater-cli analysis risk pipe-now --pipe P1",),
|
||
),
|
||
("analysis", "risk", "pipe-history"): CommandDoc(
|
||
path=("analysis", "risk", "pipe-history"),
|
||
summary="读取单条管道历史风险",
|
||
description="调用 /getpiperiskprobability/。",
|
||
options=(CommandOptionDoc("pipe", "管道 ID", required=True),),
|
||
examples=("tjwater-cli analysis risk pipe-history --pipe P1",),
|
||
),
|
||
("analysis", "risk", "network"): CommandDoc(
|
||
path=("analysis", "risk", "network"),
|
||
summary="读取全网风险",
|
||
description="组合 /getnetworkpiperiskprobabilitynow/ 与 /getpiperiskprobabilitygeometries/。",
|
||
examples=("tjwater-cli analysis risk network",),
|
||
),
|
||
("data", "timeseries", "realtime", "links"): CommandDoc(
|
||
path=("data", "timeseries", "realtime", "links"),
|
||
summary="查询实时管道时序",
|
||
description="调用 /realtime/links。",
|
||
options=(
|
||
CommandOptionDoc("start-time", "显式带时区的开始时间", required=True),
|
||
CommandOptionDoc("end-time", "显式带时区的结束时间", required=True),
|
||
),
|
||
examples=("tjwater-cli data timeseries realtime links --start-time 2025-01-02T03:00:00+08:00 --end-time 2025-01-02T04:00:00+08:00",),
|
||
),
|
||
("data", "timeseries", "realtime", "nodes"): CommandDoc(
|
||
path=("data", "timeseries", "realtime", "nodes"),
|
||
summary="查询实时节点时序",
|
||
description="调用 /realtime/nodes。",
|
||
options=(
|
||
CommandOptionDoc("start-time", "显式带时区的开始时间", required=True),
|
||
CommandOptionDoc("end-time", "显式带时区的结束时间", required=True),
|
||
),
|
||
examples=("tjwater-cli data timeseries realtime nodes --start-time 2025-01-02T03:00:00+08:00 --end-time 2025-01-02T04:00:00+08:00",),
|
||
),
|
||
("data", "timeseries", "realtime", "simulation-by-id-time"): CommandDoc(
|
||
path=("data", "timeseries", "realtime", "simulation-by-id-time"),
|
||
summary="按元素和时间查询实时模拟结果",
|
||
description="调用 /realtime/query/by-id-time。",
|
||
options=(
|
||
CommandOptionDoc("id", "元素 ID", required=True),
|
||
CommandOptionDoc("type", "元素类型:pipe 或 junction;links/nodes 是独立子命令,不是 type 取值", required=True),
|
||
CommandOptionDoc("time", "显式带时区的查询时间", required=True),
|
||
),
|
||
examples=(
|
||
"tjwater-cli data timeseries realtime simulation-by-id-time --id J1 --type junction --time 2025-01-02T03:30:00+08:00",
|
||
"tjwater-cli data timeseries realtime simulation-by-id-time --id P1 --type pipe --time 2025-01-02T03:30:00+08:00",
|
||
),
|
||
),
|
||
("data", "timeseries", "realtime", "simulation-by-time-property"): CommandDoc(
|
||
path=("data", "timeseries", "realtime", "simulation-by-time-property"),
|
||
summary="按时间和属性查询实时模拟结果",
|
||
description="调用 /realtime/query/by-time-property。pipe 属性:flow、friction、headloss、quality、reaction、setting、status、velocity;junction 属性:actual_demand、total_head、pressure、quality。",
|
||
options=(
|
||
CommandOptionDoc("type", "元素类型:pipe 或 junction;links/nodes 是独立子命令,不是 type 取值", required=True),
|
||
CommandOptionDoc("time", "显式带时区的查询时间", required=True),
|
||
CommandOptionDoc("property", "属性名;会按 type 校验可选值", required=True),
|
||
),
|
||
examples=("tjwater-cli data timeseries realtime simulation-by-time-property --type pipe --time 2025-01-02T03:30:00+08:00 --property flow",),
|
||
),
|
||
("data", "timeseries", "scheme", "links"): CommandDoc(
|
||
path=("data", "timeseries", "scheme", "links"),
|
||
summary="查询方案管道时序",
|
||
description="调用 /scheme/links。",
|
||
options=(
|
||
CommandOptionDoc("start-time", "显式带时区的开始时间", required=True),
|
||
CommandOptionDoc("end-time", "显式带时区的结束时间", required=True),
|
||
CommandOptionDoc("scheme", "方案名称"),
|
||
CommandOptionDoc("scheme-type", "方案类型"),
|
||
),
|
||
examples=("tjwater-cli data timeseries scheme links --start-time 2025-01-02T03:00:00+08:00 --end-time 2025-01-02T04:00:00+08:00 --scheme my_scheme",),
|
||
),
|
||
("data", "timeseries", "scheme", "node-field"): CommandDoc(
|
||
path=("data", "timeseries", "scheme", "node-field"),
|
||
summary="查询方案节点字段时序",
|
||
description="调用 /scheme/nodes/{node_id}/field。field 仅支持 actual_demand、total_head、pressure、quality。",
|
||
options=(
|
||
CommandOptionDoc("node", "节点 ID", required=True),
|
||
CommandOptionDoc("field", "字段名:actual_demand、total_head、pressure、quality", required=True),
|
||
CommandOptionDoc("start-time", "显式带时区的开始时间", required=True),
|
||
CommandOptionDoc("end-time", "显式带时区的结束时间", required=True),
|
||
CommandOptionDoc("scheme", "方案名称"),
|
||
CommandOptionDoc("scheme-type", "方案类型"),
|
||
),
|
||
examples=("tjwater-cli data timeseries scheme node-field --node J1 --field pressure --start-time 2025-01-02T03:00:00+08:00 --end-time 2025-01-02T04:00:00+08:00 --scheme my_scheme",),
|
||
),
|
||
("data", "timeseries", "scheme", "simulation"): CommandDoc(
|
||
path=("data", "timeseries", "scheme", "simulation"),
|
||
summary="查询方案模拟数据",
|
||
description="支持 by-id-time 与 by-scheme-time-property 两种查询。pipe 属性:flow、friction、headloss、quality、reaction、setting、status、velocity;junction 属性:actual_demand、total_head、pressure、quality。",
|
||
options=(
|
||
CommandOptionDoc("query", "查询模式:by-id-time 或 by-scheme-time-property", required=True),
|
||
CommandOptionDoc("scheme", "方案名称"),
|
||
CommandOptionDoc("scheme-type", "方案类型"),
|
||
CommandOptionDoc("id", "元素 ID(by-id-time 时必需)"),
|
||
CommandOptionDoc("time", "显式带时区的查询时间", required=True),
|
||
CommandOptionDoc("type", "元素类型:pipe 或 junction;links/nodes 是独立子命令,不是 type 取值"),
|
||
CommandOptionDoc("property", "属性名(by-scheme-time-property 时必需;会按 type 校验可选值)"),
|
||
),
|
||
examples=(
|
||
"tjwater-cli data timeseries scheme simulation --query by-id-time --id J1 --time 2025-01-02T03:30:00+08:00 --type junction --scheme my_scheme",
|
||
"tjwater-cli data timeseries scheme simulation --query by-scheme-time-property --time 2025-01-02T03:30:00+08:00 --type pipe --property flow --scheme my_scheme",
|
||
),
|
||
),
|
||
("data", "timeseries", "scada", "query"): CommandDoc(
|
||
path=("data", "timeseries", "scada", "query"),
|
||
summary="查询 SCADA 时序",
|
||
description="device-id 会被转换成后端逗号分隔参数。field 仅支持 monitored_value、cleaned_value。",
|
||
options=(
|
||
CommandOptionDoc("device-id", "设备 ID(可多次指定)", required=True, repeated=True),
|
||
CommandOptionDoc("start-time", "显式带时区的开始时间", required=True),
|
||
CommandOptionDoc("end-time", "显式带时区的结束时间", required=True),
|
||
CommandOptionDoc("field", "字段名:monitored_value、cleaned_value"),
|
||
),
|
||
examples=(
|
||
"tjwater-cli data timeseries scada query --device-id D1 --device-id D2 --start-time 2025-01-02T03:00:00+08:00 --end-time 2025-01-02T04:00:00+08:00",
|
||
"tjwater-cli data timeseries scada query --device-id D1 --start-time 2025-01-02T03:00:00+08:00 --end-time 2025-01-02T04:00:00+08:00 --field monitored_value",
|
||
),
|
||
),
|
||
("data", "timeseries", "composite"): CommandDoc(
|
||
path=("data", "timeseries", "composite"),
|
||
summary="执行复合时序查询",
|
||
description="kind 支持 scada-simulation、element-simulation、element-scada。",
|
||
options=(
|
||
CommandOptionDoc("kind", "复合查询类型", required=True),
|
||
CommandOptionDoc("feature", "特征值(可多次指定,scada-simulation 为 device_id,element-simulation 为 element_id:property,element-scada 为 element_id)", repeated=True),
|
||
CommandOptionDoc("start-time", "显式带时区的开始时间", required=True),
|
||
CommandOptionDoc("end-time", "显式带时区的结束时间", required=True),
|
||
CommandOptionDoc("scheme", "方案名称"),
|
||
CommandOptionDoc("scheme-type", "方案类型"),
|
||
CommandOptionDoc("use-cleaned", "element-scada 使用清洗值"),
|
||
),
|
||
examples=(
|
||
"tjwater-cli data timeseries composite --kind scada-simulation --feature D1 --feature D2 --start-time 2025-01-02T03:00:00+08:00 --end-time 2025-01-02T04:00:00+08:00 --scheme my_scheme",
|
||
"tjwater-cli data timeseries composite --kind element-simulation --feature J1:pressure --feature P1:flow --start-time 2025-01-02T03:00:00+08:00 --end-time 2025-01-02T04:00:00+08:00 --scheme my_scheme",
|
||
"tjwater-cli data timeseries composite --kind element-scada --feature J1 --start-time 2025-01-02T03:00:00+08:00 --end-time 2025-01-02T04:00:00+08:00 --use-cleaned",
|
||
),
|
||
),
|
||
("data", "timeseries", "composite", "pipeline-health"): CommandDoc(
|
||
path=("data", "timeseries", "composite", "pipeline-health"),
|
||
summary="查询管道健康预测",
|
||
description="调用 /composite/pipeline-health-prediction。",
|
||
options=(
|
||
CommandOptionDoc("pipe", "管道 ID", required=True),
|
||
CommandOptionDoc("start-time", "显式带时区的开始时间", required=True),
|
||
CommandOptionDoc("end-time", "显式带时区的结束时间", required=True),
|
||
),
|
||
examples=("tjwater-cli data timeseries composite pipeline-health --pipe P1 --start-time 2025-01-02T03:00:00+08:00 --end-time 2025-01-02T04:00:00+08:00",),
|
||
),
|
||
("data", "scada", "get"): CommandDoc(
|
||
path=("data", "scada", "get"),
|
||
summary="读取单条 SCADA 元数据",
|
||
description="kind 仅支持 info。",
|
||
options=(
|
||
CommandOptionDoc("kind", "SCADA 数据类型", required=True),
|
||
CommandOptionDoc("id", "记录 ID", required=True),
|
||
),
|
||
examples=("tjwater-cli data scada get --kind info --id SCADA-001",),
|
||
),
|
||
("data", "scada", "list"): CommandDoc(
|
||
path=("data", "scada", "list"),
|
||
summary="列出 SCADA 元数据",
|
||
description="kind 仅支持 info。",
|
||
options=(CommandOptionDoc("kind", "SCADA 数据类型", required=True),),
|
||
examples=("tjwater-cli data scada list --kind info",),
|
||
),
|
||
("data", "scheme", "schema"): CommandDoc(
|
||
path=("data", "scheme", "schema"),
|
||
summary="读取方案 schema",
|
||
description="调用 /getschemeschema/。",
|
||
examples=("tjwater-cli data scheme schema",),
|
||
),
|
||
("data", "scheme", "get"): CommandDoc(
|
||
path=("data", "scheme", "get"),
|
||
summary="读取单条方案",
|
||
description="调用 /getscheme/。",
|
||
options=(CommandOptionDoc("name", "方案名称", required=True),),
|
||
examples=("tjwater-cli data scheme get --name my_scheme",),
|
||
),
|
||
("data", "scheme", "list"): CommandDoc(
|
||
path=("data", "scheme", "list"),
|
||
summary="列出方案",
|
||
description="调用 /getallschemes/。",
|
||
examples=("tjwater-cli data scheme list",),
|
||
),
|
||
}
|
||
|
||
|
||
def _build_examples(doc: CommandDoc) -> list[str]:
|
||
return list(doc.examples) if doc.examples else [_build_usage(doc)]
|
||
|
||
|
||
def _is_hidden_path(path: tuple[str, ...]) -> bool:
|
||
return any(path[: len(prefix)] == prefix for prefix in HIDDEN_PATH_PREFIXES)
|
||
|
||
|
||
def is_hidden_path(path: tuple[str, ...]) -> bool:
|
||
return _is_hidden_path(path)
|
||
|
||
|
||
def has_subcommands(path_prefix: tuple[str, ...]) -> bool:
|
||
return any(
|
||
not _is_hidden_path(doc.path)
|
||
and doc.path[: len(path_prefix)] == path_prefix
|
||
and len(doc.path) > len(path_prefix)
|
||
for doc in COMMAND_DOCS.values()
|
||
)
|
||
|
||
|
||
def get_group_summary(path_prefix: tuple[str, ...]) -> str:
|
||
return GROUP_SUMMARIES.get(path_prefix, f"{' '.join(path_prefix)} 可用子命令")
|
||
|
||
|
||
def list_capabilities() -> dict[str, object]:
|
||
seen: set[tuple[str, ...]] = set()
|
||
commands: list[dict[str, str]] = []
|
||
for doc in sorted(COMMAND_DOCS.values(), key=lambda item: item.path):
|
||
if _is_hidden_path(doc.path):
|
||
continue
|
||
prefix = doc.path[:1]
|
||
if prefix in seen:
|
||
continue
|
||
seen.add(prefix)
|
||
commands.append(
|
||
{
|
||
"command": " ".join(prefix),
|
||
"summary": get_group_summary(prefix),
|
||
}
|
||
)
|
||
return {
|
||
"ok": True,
|
||
"schema_version": SCHEMA_VERSION,
|
||
"summary": "可用一级菜单",
|
||
"menu_level": 1,
|
||
"commands": commands,
|
||
}
|
||
|
||
|
||
def get_command_doc(path: tuple[str, ...]) -> dict[str, object] | None:
|
||
if _is_hidden_path(path):
|
||
return None
|
||
doc = COMMAND_DOCS.get(path)
|
||
if doc is None:
|
||
return None
|
||
return {
|
||
"ok": True,
|
||
"schema_version": SCHEMA_VERSION,
|
||
"summary": doc.summary,
|
||
"command": " ".join(doc.path),
|
||
"description": doc.description,
|
||
"usage": _build_usage(doc),
|
||
"options": [
|
||
{
|
||
"name": option.name,
|
||
"description": option.description,
|
||
"required": option.required,
|
||
"repeated": option.repeated,
|
||
"default": option.default,
|
||
}
|
||
for option in doc.options
|
||
],
|
||
"examples": _build_examples(doc),
|
||
"next_commands": list(doc.next_commands),
|
||
"output": doc.output,
|
||
}
|
||
|
||
|
||
def list_subcommands(path_prefix: tuple[str, ...], summary: str | None = None) -> dict[str, object]:
|
||
seen: set[str] = set()
|
||
commands: list[dict[str, str]] = []
|
||
for doc in sorted(COMMAND_DOCS.values(), key=lambda item: item.path):
|
||
if _is_hidden_path(doc.path):
|
||
continue
|
||
if doc.path[: len(path_prefix)] != path_prefix or len(doc.path) <= len(path_prefix):
|
||
continue
|
||
subcommand = doc.path[len(path_prefix)]
|
||
if subcommand in seen:
|
||
continue
|
||
seen.add(subcommand)
|
||
current_path = (*path_prefix, subcommand)
|
||
is_group = has_subcommands(current_path)
|
||
usage = f"tjwater-cli {' '.join(current_path)} help" if is_group else (doc.examples[0] if doc.examples else _build_usage(doc))
|
||
commands.append(
|
||
{
|
||
"command": " ".join(current_path),
|
||
"summary": get_group_summary(current_path) if is_group else doc.summary,
|
||
"usage": usage,
|
||
"example": f"tjwater-cli {' '.join(current_path)} help" if is_group else _build_examples(doc)[0],
|
||
}
|
||
)
|
||
return {
|
||
"ok": True,
|
||
"schema_version": SCHEMA_VERSION,
|
||
"summary": summary or get_group_summary(path_prefix),
|
||
"commands": commands,
|
||
}
|
||
|
||
|
||
def _build_usage(doc: CommandDoc) -> str:
|
||
parts = ["tjwater-cli", *doc.path]
|
||
for option in doc.options:
|
||
placeholder = option.name.upper().replace("-", "_")
|
||
if option.required:
|
||
parts.extend([f"--{option.name}", f"<{placeholder}>"])
|
||
else:
|
||
parts.append(f"[--{option.name} <{placeholder}>]")
|
||
return " ".join(parts)
|