Files
TJWaterAgent/cli/src/commands/data.ts
T

177 lines
9.5 KiB
TypeScript

import { SCADA_FIELDS, type ElementType } from "../core/constants.js";
import { CliError } from "../core/errors.js";
import { emitApi } from "../core/http.js";
import { fieldsFor, optionalString, parseOptions, requiredString, requiredStringArray, validateChoice } from "../core/options.js";
import { resolveScheme } from "../core/runtime.js";
import { parseTime } from "../core/time.js";
import type { HandlerMap, RuntimeContext } from "../core/types.js";
function backendElementType(type: ElementType): "link" | "node" {
return type === "pipe" ? "link" : "node";
}
function rangeGet(ctx: RuntimeContext, argv: string[], summary: string, path: string): Promise<void> {
const { values } = parseOptions(argv);
return emitApi(ctx, summary, {
method: "GET",
path,
params: { start_time: parseTime(requiredString(values, "start-time"), "--start-time"), end_time: parseTime(requiredString(values, "end-time"), "--end-time") },
requireProject: true,
});
}
function realtimeByIdTime(ctx: RuntimeContext, argv: string[]): Promise<void> {
const { values } = parseOptions(argv);
const type = validateChoice(requiredString(values, "type"), ["pipe", "junction"] as const, "--type");
return emitApi(ctx, "读取实时模拟数据成功", {
method: "GET",
path: "/timeseries/realtime/simulation-results",
params: { id: requiredString(values, "id"), type: backendElementType(type), query_time: parseTime(requiredString(values, "time"), "--time") },
requireProject: true,
});
}
function realtimeByTimeProperty(ctx: RuntimeContext, argv: string[]): Promise<void> {
const { values } = parseOptions(argv);
const type = validateChoice(requiredString(values, "type"), ["pipe", "junction"] as const, "--type");
return emitApi(ctx, "读取实时属性聚合数据成功", {
method: "GET",
path: "/timeseries/realtime/records",
params: { type: backendElementType(type), query_time: parseTime(requiredString(values, "time"), "--time"), property: validateChoice(requiredString(values, "property"), fieldsFor(type), "--property") },
requireProject: true,
});
}
function schemeLinks(ctx: RuntimeContext, argv: string[]): Promise<void> {
const { values } = parseOptions(argv);
return emitApi(ctx, "读取方案管道数据成功", {
method: "GET",
path: "/timeseries/schemes/links",
params: {
scheme_name: resolveScheme(ctx, optionalString(values, "scheme"), true),
scheme_type: optionalString(values, "scheme-type") || "simulation",
start_time: parseTime(requiredString(values, "start-time"), "--start-time"),
end_time: parseTime(requiredString(values, "end-time"), "--end-time"),
},
requireProject: true,
});
}
function schemeNodeField(ctx: RuntimeContext, argv: string[]): Promise<void> {
const { values } = parseOptions(argv);
return emitApi(ctx, "读取方案节点字段成功", {
method: "GET",
path: `/timeseries/schemes/nodes/${requiredString(values, "node")}/field`,
params: {
field: validateChoice(requiredString(values, "field"), fieldsFor("junction"), "--field"),
scheme_name: resolveScheme(ctx, optionalString(values, "scheme"), true),
scheme_type: optionalString(values, "scheme-type") || "simulation",
start_time: parseTime(requiredString(values, "start-time"), "--start-time"),
end_time: parseTime(requiredString(values, "end-time"), "--end-time"),
},
requireProject: true,
});
}
function schemeSimulation(ctx: RuntimeContext, argv: string[]): Promise<void> {
const { values } = parseOptions(argv);
const query = validateChoice(requiredString(values, "query"), ["by-id-time", "by-scheme-time-property"] as const, "--query");
const type = validateChoice(optionalString(values, "type") || "pipe", ["pipe", "junction"] as const, "--type") as ElementType;
const params: Record<string, unknown> = {
scheme_name: resolveScheme(ctx, optionalString(values, "scheme"), true),
scheme_type: optionalString(values, "scheme-type") || "simulation",
query_time: parseTime(requiredString(values, "time"), "--time"),
type: backendElementType(type),
};
if (query === "by-id-time") {
params.id = requiredString(values, "id");
return emitApi(ctx, "读取方案单点模拟数据成功", { method: "GET", path: "/timeseries/schemes/simulation-results", params, requireProject: true });
}
params.property = validateChoice(requiredString(values, "property"), fieldsFor(type), "--property");
return emitApi(ctx, "读取方案属性聚合数据成功", { method: "GET", path: "/timeseries/schemes/records", params, requireProject: true });
}
function scadaQuery(ctx: RuntimeContext, argv: string[]): Promise<void> {
const { values } = parseOptions(argv, { "device-id": "repeat" });
const params: Record<string, unknown> = {
device_ids: requiredStringArray(values, "device-id").join(","),
start_time: parseTime(requiredString(values, "start-time"), "--start-time"),
end_time: parseTime(requiredString(values, "end-time"), "--end-time"),
};
const field = optionalString(values, "field");
if (field) params.field = validateChoice(field, SCADA_FIELDS, "--field");
return emitApi(ctx, "读取 SCADA 时序成功", { method: "GET", path: field ? "/timeseries/scada-readings/fields" : "/timeseries/scada-readings", params, requireProject: true });
}
function composite(ctx: RuntimeContext, argv: string[]): Promise<void> {
const { values } = parseOptions(argv, { feature: "repeat", "use-cleaned": "boolean" });
const kind = validateChoice(requiredString(values, "kind"), ["scada-simulation", "element-simulation", "element-scada"] as const, "--kind");
const params: Record<string, unknown> = {
start_time: parseTime(requiredString(values, "start-time"), "--start-time"),
end_time: parseTime(requiredString(values, "end-time"), "--end-time"),
};
const schemeName = resolveScheme(ctx, optionalString(values, "scheme"));
if (schemeName) Object.assign(params, { scheme_name: schemeName, scheme_type: optionalString(values, "scheme-type") || "simulation" });
if (kind === "scada-simulation") params.device_ids = requiredStringArray(values, "feature").join(",");
else if (kind === "element-simulation") params.feature_infos = requiredStringArray(values, "feature").join(",");
else {
const feature = requiredStringArray(values, "feature");
if (feature.length !== 1) throw new CliError("CLI 参数错误", "FEATURE_REQUIRED", "element-scada requires exactly one --feature as element_id", 2);
params.element_id = feature[0];
params.use_cleaned = Boolean(values["use-cleaned"]);
}
const paths = {
"scada-simulation": "/timeseries/views/scada-simulations",
"element-simulation": "/timeseries/views/element-simulations",
"element-scada": "/timeseries/views/element-scada-readings",
} as const;
return emitApi(ctx, kind === "scada-simulation" ? "读取复合 SCADA-模拟数据成功" : kind === "element-simulation" ? "读取复合元素模拟数据成功" : "读取元素关联 SCADA 数据成功", { method: "GET", path: paths[kind], params, requireProject: true });
}
function pipelineHealth(ctx: RuntimeContext, argv: string[]): Promise<void> {
const { values } = parseOptions(argv);
requiredString(values, "pipe");
requiredString(values, "start-time");
return emitApi(ctx, "读取管道健康预测成功", {
method: "GET",
path: "/pipeline-health-predictions",
params: { query_time: parseTime(requiredString(values, "end-time"), "--end-time") },
requireProject: true,
});
}
function dataScadaGet(ctx: RuntimeContext, argv: string[]): Promise<void> {
const { values } = parseOptions(argv);
validateChoice(requiredString(values, "kind"), ["info"] as const, "--kind");
return emitApi(ctx, "读取 SCADA 数据成功", { method: "GET", path: "/scada-info/detail", params: { id: requiredString(values, "id") }, requireProject: true });
}
function dataScadaList(ctx: RuntimeContext, argv: string[]): Promise<void> {
const { values } = parseOptions(argv);
validateChoice(requiredString(values, "kind"), ["info"] as const, "--kind");
return emitApi(ctx, "读取 SCADA 列表成功", { method: "GET", path: "/scada-info", requireProject: true });
}
function dataSchemeGet(ctx: RuntimeContext, argv: string[]): Promise<void> {
const { values } = parseOptions(argv);
return emitApi(ctx, "读取方案成功", { method: "GET", path: "/schemes/detail", params: { schema_name: requiredString(values, "name") }, requireProject: true });
}
export const dataHandlers: HandlerMap = {
"data timeseries realtime links": (ctx, argv) => rangeGet(ctx, argv, "读取实时管道数据成功", "/timeseries/realtime/links"),
"data timeseries realtime nodes": (ctx, argv) => rangeGet(ctx, argv, "读取实时节点数据成功", "/timeseries/realtime/nodes"),
"data timeseries realtime simulation-by-id-time": realtimeByIdTime,
"data timeseries realtime simulation-by-time-property": realtimeByTimeProperty,
"data timeseries scheme links": schemeLinks,
"data timeseries scheme node-field": schemeNodeField,
"data timeseries scheme simulation": schemeSimulation,
"data timeseries scada query": scadaQuery,
"data timeseries composite": composite,
"data timeseries composite pipeline-health": pipelineHealth,
"data scada get": dataScadaGet,
"data scada list": dataScadaList,
"data scheme schema": (ctx) => emitApi(ctx, "读取方案 schema 成功", { method: "GET", path: "/network-schemas/scheme", requireProject: true }),
"data scheme get": dataSchemeGet,
"data scheme list": (ctx) => emitApi(ctx, "读取方案列表成功", { method: "GET", path: "/schemes", requireProject: true }),
};