feat(scada): add project monitoring replay
This commit is contained in:
@@ -19,13 +19,18 @@ CREATE TABLE IF NOT EXISTS projects (
|
||||
gs_workspace VARCHAR(100) UNIQUE NOT NULL,
|
||||
map_extent JSONB,
|
||||
map_config JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
settings JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
status VARCHAR(20) DEFAULT 'active' NOT NULL,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
CONSTRAINT projects_status_check CHECK (status IN ('active', 'inactive', 'archived'))
|
||||
CONSTRAINT projects_status_check CHECK (status IN ('active', 'inactive', 'archived')),
|
||||
CONSTRAINT projects_settings_object_check CHECK (jsonb_typeof(settings) = 'object')
|
||||
);
|
||||
|
||||
ALTER TABLE projects ADD COLUMN IF NOT EXISTS map_config JSONB NOT NULL DEFAULT '{}'::jsonb;
|
||||
ALTER TABLE projects ADD COLUMN IF NOT EXISTS settings JSONB NOT NULL DEFAULT '{}'::jsonb;
|
||||
COMMENT ON COLUMN projects.settings IS
|
||||
'项目级通用配置(JSON 对象,不存放密钥);scada_monitoring_interval_seconds 为监测任务间隔秒数。';
|
||||
COMMENT ON COLUMN projects.map_config IS
|
||||
'项目级地图配置(JSON);place_search 保存地名搜索启用状态、服务商、行政区编码及区域名称;保留既有图例与坐标参考配置。';
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
BEGIN;
|
||||
DO $$ BEGIN
|
||||
IF current_database() NOT IN ('tjwater_v2', 'tjwater2_v2') THEN
|
||||
RAISE EXCEPTION '031_scada_replays requires an explicitly verified SCADA demo project';
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS peripheral_sample.scada_replays (
|
||||
project_id uuid NOT NULL,
|
||||
replay_id uuid NOT NULL,
|
||||
request_id uuid NOT NULL,
|
||||
status text NOT NULL CHECK (status IN ('ready','paused','completed','stopped','failed')),
|
||||
document jsonb NOT NULL,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (project_id,replay_id),
|
||||
UNIQUE (project_id,request_id)
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS scada_replays_status_idx
|
||||
ON peripheral_sample.scada_replays(project_id,status,created_at DESC);
|
||||
CREATE TABLE IF NOT EXISTS peripheral_sample.scada_replay_batches (
|
||||
project_id uuid NOT NULL,
|
||||
replay_id uuid NOT NULL,
|
||||
sequence bigint NOT NULL,
|
||||
stage text NOT NULL CHECK(stage IN ('selected','clean_prepared','cleaned','detected')),
|
||||
document jsonb NOT NULL,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY(project_id,replay_id,sequence),
|
||||
FOREIGN KEY(project_id,replay_id) REFERENCES peripheral_sample.scada_replays(project_id,replay_id)
|
||||
);
|
||||
COMMENT ON TABLE peripheral_sample.scada_replays IS 'SCADA 演示回放的权威控制状态与处理检查点,不保存正式原始观测';
|
||||
COMMENT ON COLUMN peripheral_sample.scada_replays.project_id IS '经认证与路由校验的所属项目';
|
||||
COMMENT ON COLUMN peripheral_sample.scada_replays.replay_id IS '独立回放身份,不等同 Agent 执行编号';
|
||||
COMMENT ON COLUMN peripheral_sample.scada_replays.request_id IS '创建请求的稳定幂等编号';
|
||||
COMMENT ON COLUMN peripheral_sample.scada_replays.status IS '供领取和约束使用的 document.status 查询投影';
|
||||
COMMENT ON COLUMN peripheral_sample.scada_replays.document IS '冻结配置、设备快照、时钟、检查点、规则状态和命令回执';
|
||||
COMMENT ON COLUMN peripheral_sample.scada_replays.created_at IS '实际创建时间';
|
||||
COMMENT ON COLUMN peripheral_sample.scada_replays.updated_at IS '实际控制或进度更新时间';
|
||||
COMMENT ON TABLE peripheral_sample.scada_replay_batches IS 'SCADA raw 引用、清洗输出及检测阶段的恢复凭证,禁止重写 raw';
|
||||
COMMENT ON COLUMN peripheral_sample.scada_replay_batches.project_id IS '所属项目';
|
||||
COMMENT ON COLUMN peripheral_sample.scada_replay_batches.replay_id IS '所属回放';
|
||||
COMMENT ON COLUMN peripheral_sample.scada_replay_batches.sequence IS '回放内单调批次序号';
|
||||
COMMENT ON COLUMN peripheral_sample.scada_replay_batches.stage IS '已提交处理阶段';
|
||||
COMMENT ON COLUMN peripheral_sample.scada_replay_batches.document IS '观测键、raw 摘要、确定的清洗结果与检测事件';
|
||||
COMMENT ON COLUMN peripheral_sample.scada_replay_batches.created_at IS '实际登记批次时间';
|
||||
COMMIT;
|
||||
@@ -0,0 +1,54 @@
|
||||
BEGIN;
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF to_regclass('public.project_databases') IS NULL
|
||||
OR to_regclass('public.user_project_membership') IS NULL THEN
|
||||
RAISE EXCEPTION '033_metadata_project_settings must run in the project metadata database';
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
ALTER TABLE public.projects
|
||||
ADD COLUMN IF NOT EXISTS settings jsonb NOT NULL DEFAULT '{}'::jsonb;
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint
|
||||
WHERE conrelid = 'public.projects'::regclass
|
||||
AND conname = 'projects_settings_object_check'
|
||||
) THEN
|
||||
ALTER TABLE public.projects
|
||||
ADD CONSTRAINT projects_settings_object_check
|
||||
CHECK (jsonb_typeof(settings) = 'object');
|
||||
END IF;
|
||||
|
||||
IF EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = 'public' AND table_name = 'projects'
|
||||
AND column_name = 'scada_monitoring_interval_seconds'
|
||||
) THEN
|
||||
IF EXISTS (
|
||||
SELECT 1 FROM public.projects
|
||||
WHERE scada_monitoring_interval_seconds IS NOT NULL
|
||||
AND settings ? 'scada_monitoring_interval_seconds'
|
||||
AND settings->'scada_monitoring_interval_seconds'
|
||||
IS DISTINCT FROM to_jsonb(scada_monitoring_interval_seconds)
|
||||
) THEN
|
||||
RAISE EXCEPTION 'Conflicting SCADA monitoring intervals; resolve before migration';
|
||||
END IF;
|
||||
|
||||
UPDATE public.projects
|
||||
SET settings = settings || jsonb_build_object(
|
||||
'scada_monitoring_interval_seconds', scada_monitoring_interval_seconds
|
||||
)
|
||||
WHERE scada_monitoring_interval_seconds IS NOT NULL;
|
||||
|
||||
ALTER TABLE public.projects DROP COLUMN scada_monitoring_interval_seconds;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
COMMENT ON COLUMN public.projects.settings IS
|
||||
'项目级通用配置(JSON 对象,不存放密钥);scada_monitoring_interval_seconds 为监测任务间隔秒数。';
|
||||
|
||||
COMMIT;
|
||||
@@ -2,7 +2,7 @@
|
||||
name: burst-report
|
||||
description: 调查供水爆管上报,形成有依据的候选位置、隔离阀门、影响范围和后续处置建议。
|
||||
metadata:
|
||||
version: "2.0.6"
|
||||
version: "2.0.8"
|
||||
---
|
||||
|
||||
# 爆管上报处置
|
||||
@@ -13,6 +13,8 @@ metadata:
|
||||
|
||||
读取当前任务、事件时刻、地点、来源、已有报告、证据、动作和反馈。新一轮优先检查新增事实和上轮未决项,按时间、来源、对象及输入比较新旧结果,不按 ID 推断先后,也不因原工单未更新就断言没有新证据。保留本流程名称和版本。
|
||||
|
||||
若任务来源带有 `replay_context`,这是 SCADA 历史回放中的疑似爆管演示。先读取任务摘要中的步长监测结论,再用 `query_scada_readings` 核对冻结批次;不得查询知识截止之后的数据。回放中的 `run_burst_location` 只接受 monitoring 模式,并要求显式提供本轮已处理范围内的异常窗和正常对照窗;Server 会从冻结清洗输出构造计算输入。缺少有依据的 `burst_leakage` 时保留“定位待补充”,不得用出厂流量增量、压力下降或默认值替代。回放结果保持 synthetic,不发布真实工单或设备动作。
|
||||
|
||||
## 定位与影响分析
|
||||
|
||||
根据现有线索自主选择必要步骤:
|
||||
@@ -26,9 +28,19 @@ metadata:
|
||||
|
||||
查询错误、权限拒绝或接口故障不是缺数证据。必要分析无法执行时,说明失败步骤和已经完成的部分,不借有限摘要宣布调查完成。
|
||||
|
||||
## 事件前后影响说明
|
||||
|
||||
每轮按实际证据说明以下阶段的影响,给出结果或具体限制;尚未发生的处置列为预测和待验证项:
|
||||
|
||||
1. **事件前与爆管后、隔离前**:核对正常基线和异常窗口,说明压力、流量变化及已覆盖的异常点位、资产和区域。候选管段及破口面积有依据时,可用 `run_burst_simulation` 补充情景水力影响,标明假设。漏量估计须说明边界流量、正常用水及储量变化等依据;有可靠漏量序列和时间覆盖时可累计漏水量,保留单位、方法和不确定性。定位工具的 `burst_leakage` 是输入,不能当成反演所得漏量。
|
||||
2. **关阀隔离方案**:说明止漏目标、直接隔离节点和关阀后新增失去水源连接的节点,分别保留 `affected_nodes` 与 `supply_affected_nodes` 及其计数。结合关阀水力结果说明预计停水、低压或供水不足的范围和覆盖限制;有用户关联资料时说明受影响用户、重要设施及保障需求。拓扑失源、模型预测和现场实际停水分别标注,不把节点数当户数。
|
||||
3. **实际隔离与恢复供水后**:后续轮次按实际关阀、抢修和恢复时间读取前后监测与现场反馈,对照预测核查止漏效果、实际影响范围和恢复情况,说明持续低压、异常流量、再次异常及尚待验证的影响。核对正常基线、观察窗口和判定依据,工单状态或单个正常读数不足以证明影响消除。
|
||||
|
||||
比较须核对对象、单位、时间对齐、模型版本、需水与水源边界、泵阀状态及计算设置;区分实测变化与模型方案差异。关阀工具不会自动继承爆管情景,条件不同的独立计算不能直接作为同一事故前后效果。可比时给出变化量和方案差异,缺少可比基准时说明当前结果及缺口,不补造改善比例。必要的紧急核验、通知和供水保障不等待可选的完整模拟。
|
||||
|
||||
## 处置与报告
|
||||
|
||||
报告分别给出位置候选及依据、隔离阀门及可用性、替代方案、拓扑与水力影响、用户影响边界,以及处置和闭环缺口。只有初步结果时明确范围,不宣称已经定位、确诊或闭环。位置、候选、监测、影响和阀门方案按实际调查步骤同步展示,遵循后台展示规则,不用报告定位链接代替过程展示。覆盖面保留分组、缺失几何和示意边界,不能当作实际停水、水力影响或用户服务边界。无数据或展示失败时说明具体限制;展示不替代证据,也不要求等待浏览器。
|
||||
报告分别给出位置候选及依据、隔离阀门及可用性、替代方案、事件前后分阶段的拓扑与水力影响、用户影响边界,以及处置和闭环缺口。影响说明保留时间窗、对象、证据、实测或预测属性及限制。只有初步结果时明确范围,不宣称已经定位、确诊或闭环。位置、候选、监测、影响和阀门方案按实际调查步骤同步展示,遵循后台展示规则,不用报告定位链接代替过程展示。覆盖面保留分组、缺失几何和示意边界,不能当作实际停水、水力影响或用户服务边界。无数据或展示失败时说明具体限制;展示不替代证据,也不要求等待浏览器。
|
||||
|
||||
形成具体建议后,先保存阶段结论,再提议必要动作。人工核验、通知、定位隔离、抢修、适用的清洗复测和恢复回访使用关联的 `work_order_type=general` 草稿;原爆管事件保持独立。草稿写明位置、任务、依赖、执行前核验和回执要求。没有通知适配器时明确由人工实施。设备命令仅用于真实可控目标,审批和执行由 Server 控制。
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
---
|
||||
name: scada-anomaly
|
||||
description: 调查 SCADA 回放中的异常信号,区分读数质量与运行异常,形成可追溯的演示报告。
|
||||
metadata:
|
||||
version: "1.0.1"
|
||||
---
|
||||
|
||||
# SCADA 回放异常调查
|
||||
|
||||
先读取任务上下文和来源中的 replay_context,核对规则、设备、单位、异常时刻及知识截止时间。数据来自已存 SCADA 的演示回放,不代表新采集的现场故障。
|
||||
|
||||
通过 query_scada_readings 读取事件前后本轮已处理的观测;查询结束时间不得晚于 knowledge_cutoff。结合 monitored_value 与 cleaned_value 判断数值变化,不将被可靠采集的低压或水质变化当作数据错误。缺测、无效值和未完成清洗应明确记录。
|
||||
|
||||
报告说明事件前后影响:在已开放且已处理的观测范围内,核对异常前参考、异常期间及已有恢复观测,列出压力、流量或水质变化、持续时间、涉及测点和已核实的资产关联。只有对象、单位、时间与运行条件可比时才给出变化量;说明参考窗口、证据和覆盖限制。尚无恢复观测时列为待验证,读数恢复不能证明现场修复或用户影响消除。停水范围、关阀影响及泄漏量需要相应拓扑、水力、流量平衡或现场依据;当前证据无法支持时明确待分析,不由单点低压推定停水区、受影响户数或漏量。
|
||||
|
||||
当前回放调查仅开放冻结 SCADA 证据、设备与模型目录;不支持原生计算或绕过回放上限的其他数据入口。回放前历史用于后台基线初始化,当前证据接口不返回该部分。需要更多历史或进一步计算时,报告具体缺口,不能读取未来或虚构分析结果。
|
||||
|
||||
报告列出观测事实、规则信号、质量问题、尚未确认的原因和建议核查。压力异常不等于已确认爆管,浓度变化不等于已确认污染。回放只生成演示分析与报告,不创建真实现场工单、不下发设备命令。
|
||||
Reference in New Issue
Block a user