简介:这是一套面向水务公司及智慧水务方案设计、售前咨询与信息化建设人员的数字化管控平台建设方案PPT,共41页,围绕供水行业信息化痛点,梳理从应用背景、设计思路、系统架构到产品功能、运行环境与产品优势的完整思路。内容重点覆盖生产运营、服务营销、综合管理三大业务体系,涉及SCADA、水力建模、智能调度、水质与管网监测、企业级GIS、共享交换、中心数据库、数字供水门户、营销客服、工程资产、移动办公及决策分析等模块,可用于方案汇报、项目立项与投标参考。资源包含1个pptx文件,压缩包约18.4MB,开箱即可查阅与二次编辑。目前已有110人学习下载,适合需要快速搭建智慧供水平台框架、理解业务集成与数据集成路径的从业者参考。
1. 智慧供水数字化管控平台不是一块大屏:41页方案里真正值得抄的部分
很多水务集团的信息化验收会最后都开成了大屏演示会:调度中心曲面屏亮起来,管网在地图上流动,领导点头,项目结项,第二年发现没人登录。那份41页的《水务公司智慧供水数字化管控平台建设方案》PPT里,真正把页数花在刀刃上的,其实是数据及业务支撑平台的4页和三大业务体系的拆解,而不是那些炫技的可视化效果图。
方案对行业现状的判断只有三句话,却基本写完了供水企业这十年的病历:硬件设备多、软件应用少;信息系统相对独立、协同管理少;缺少统一支撑,数据不共享、缺整合和规划。智慧供水要解的题,不是再上一个新系统,而是把已经躺在机房里的SCADA、营销、热线、资产系统收口到一套数字化管控平台的账本上。
这份pptx适合三类人翻:水务集团信息化负责人拿它判断自家系统该怎么收口,集成商售前拿它把功能清单映射成工期和接口工作量,写SCADA对接、GIS入库、营销数据同步的开发拿它对齐表结构和责任边界。它讲的是智慧水务从应用背景、设计思路、系统架构到产品功能、运行环境、产品优势的一条完整链路,其中最值得反复读的是"一个统一的应用及数据支撑平台"这个提法。
2. 从SCADA到企业级GIS:管控平台分层架构与数据底座怎么选
先明确一件事:智慧供水数字化管控平台不是一个软件,而是四层结构加上一堆既有系统的重新编排。方案里的架构图画得很满,落到实施就得回答三个问题——采集侧用什么协议接、中心数据库怎么分库、GIS和门户为什么必须放在平台层而不是应用层。
2.1 四层架构与"统一规划、分步建设"的边界
按方案的设计思路,四层是这样切的:感知层是压力计、流量计、水质在线仪、液位计、二次供水泵房RTU和安保视频;数据层是共享交换系统加中心数据库;平台层是业务及数据集成支撑平台、企业级GIS、数字供水门户;应用层是生产运营、服务营销、综合管理三大业务体系。层次切得对不对,判断标准只有一个:换掉应用层任何一个子系统,下面三层要不要动。如果换营销系统就得改数据库表结构,说明分层是假的。
方案里那句"整合资源,保护投资"容易被当成套话,实际操作中它对应一个很硬的约束——中心数据库不能推倒重来。常见做法是给旧系统加一层适配:营销系统继续用它的库,只把抄表数据、用户数据按约定口径同步到中心库,旧系统该升级升级,该保留保留。数字化管控平台建设最怕的就是一上来要求全部换新,预算一年批不下来,项目就死在PPT阶段。
分步建设还有个容易被忽略的细节:先建中心数据库和共享交换,还是先建门户和GIS。我一般建议先建中心数据库加共享交换,再上门户。理由很实际——门户是权限和展示,没有统一数据源的时候,门户只能做成各系统的超链接集合,做成一个跳转页面就失去了管控平台的意义。
2.2 采集侧协议怎么挑:Modbus TCP、OPC UA 与 MQTT 的分工
供水现场的协议比很多人想的杂。厂站DCS、PLC多用OPC UA或Modbus TCP,管网压力流量用带无线远传的RTU,二次供水泵房数量多且分散,视频走平台级联。协议不是越新越好,而是要跟设备生命周期对齐。下面这段是采集侧最常见的Modbus TCP轮询代码,加了断线重连和量纲换算:
# 管网压力/流量轮询采集,Modbus TCP,量纲换算后经MQTT上报 from pymodbus.client import ModbusTcpClient import time, json, paho.mqtt.client as mqtt SCALE = 0.001 # 仪表寄存器为整数,压力实际单位 MPa,系数 0.001 REG_ADDR = 0x0000 # 压力寄存器起始地址,按仪表手册改 SAMPLES = 3 # 连续采样次数,用于剔除单点抖动 client = ModbusTcpClient("192.168.10.31", port=502, timeout=3) mq = mqtt.Client(client_id="press-gw-01") mq.connect("10.0.0.12", 1883, 60) def read_pressure(slave_id): vals = [] for _ in range(SAMPLES): rr = client.read_holding_registers(REG_ADDR, 2, slave=slave_id) # 32位浮点占2个寄存器 if rr.isError(): continue raw = (rr.registers[0] << 16) | rr.registers[1] vals.append(raw * SCALE) time.sleep(0.2) if not vals: return None return round(sum(vals) / len(vals), 3) while True: if not client.connected: client.connect() # 断线重连,RTU掉线是常态 p = read_pressure(slave_id=1) if p is not None: mq.publish("water/press/01-0231", json.dumps({"ts": int(time.time()), "v": p})) time.sleep(5)这段代码有三个参数决定成败:SAMPLES控制抖动,管网压力在用水高峰时会跳,单点值直接入库会污染后面的告警和调度;SCALE必须跟仪表量程卡一致,现场最常见的错误是把0.001写成0.01,压力显示大十倍却没人发现;timeout设3秒,管网RTU走无线时延高,设1秒会大面积误判离线。协议选型上,我一般这样分:厂站内部用OPC UA,字段自带类型和时标,不用手工拼寄存器;管网仪表用Modbus TCP,兼容性好、成本低;分散的泵房和DMA计量点用MQTT上报,因为要走无线,且允许消息短时堆积后补传。视频不走这套,单独接流媒体服务,只把设备在线状态和告警事件推到平台。
2.3 中心数据库分库设计:八类库各放什么
方案里中心数据库列了八类:运行运营数据库、供水管网数据库、客服数据库、营销数据库、设施资源数据库、基础地形数据库、影像数据库、视频数据库。这个划分不是随便拼的,它对应三种存储引擎。运行运营是高频时序,管网和地形影像是空间数据,营销客服设施资源是标准关系数据。
| 库名 | 存放内容 | 写入频率 | 建议引擎 |
|---|---|---|---|
| 运行运营库 | 压力、流量、水质、液位、能耗 | 秒级到分钟级 | 时序库或分区表 |
| 供水管网库 | 管段、阀门、消火栓、DMA分区 | 变更驱动 | 空间数据库 |
| 营销数据库 | 用户、水表、抄表、账单 | 日批 | 关系数据库 |
| 客服数据库 | 工单、投诉、热线录音索引 | 事件驱动 | 关系数据库 |
| 设施资源库 | 厂站、泵房、设备台账 | 变更驱动 | 关系数据库 |
| 基础地形/影像库 | 底图、卫星影像、DEM | 低频 | 空间数据库+对象存储 |
测点元数据表建议和时序数据分开,元数据变更少、查询多,放在关系库里做约束:
-- 测点主数据:所有监测点、DMA分区归属和量纲的唯一口径 CREATE TABLE mon_point ( point_id VARCHAR(32) PRIMARY KEY, -- 测点编码,如 PRESS-01-0231 point_type SMALLINT NOT NULL, -- 1压力 2流量 3水质 4液位 5能耗 6视频 station_id VARCHAR(32), -- 所属厂站/泵房/二次供水小区 dma_code VARCHAR(16), -- 所属DMA分区编码 unit VARCHAR(8), -- 量纲:MPa、m3/h、NTU online_flag SMALLINT DEFAULT 0 -- 0离线 1在线,由心跳任务维护 ); -- 时序数据按天分区,避免单表过亿后查询变慢 CREATE TABLE ts_monitor_data ( point_id VARCHAR(32) NOT NULL, sample_ts TIMESTAMP NOT NULL, value NUMERIC(12,3), quality SMALLINT DEFAULT 0 -- 0正常 1可疑 2插补 3人工置数 ) PARTITION BY RANGE (sample_ts);quality这个字段看着多余,实际是后面所有分析的前提。仪表掉线、量程溢出、通讯重传产生的值如果和真实数据混在一起,漏损率、产销差、夜间最小流量全部失真。常见做法是采集侧就给值打标记,插补出来的数据单独打2,分析时按需过滤,而不是事后猜哪条数据是假的。
3. 数据及业务支撑平台落地:共享交换、企业级GIS与统一门户
方案把数据及业务支撑平台概括为四件套:共享交换系统、中心数据库、企业级GIS、数字供水门户。这四件套的关系是:共享交换负责流动,中心数据库负责沉淀,GIS负责空间维度的表达,门户负责人和权限的对齐。下面按落地顺序拆。
3.1 共享交换系统:中心库与权属库的增量同步
方案对共享交换的定义很准确:实现供水企业各下属单位和部门之间数据的实时更新,保持中心数据和各单位或部门权属数据的一致性和同步性。关键词是"权属"——数据归谁管、谁能改,这个不定义清楚,同步就会出现双向覆盖。
同步策略按数据特性分三种,选错了就是无穷无尽的扯皮:
| 数据类别 | 同步方向 | 策略 | 冲突处理 |
|---|---|---|---|
| 监测时序数据 | 单向,现场→中心 | 时间戳水位增量 | 无冲突,幂等写入 |
| 用户/抄表数据 | 单向,营销→中心 | 每日批+变更标识 | 以营销系统为准 |
| 设备台账 | 双向 | 接口调用,禁止直连库 | 以设施资源库为准 |
| 工单状态 | 单向,客服→中心 | 事件推送+定时对账 | 中心库只读 |
增量同步不要用全量对比,抄表数据一天几十万行,全量跑一次够呛。下面是一个基于水位时间戳加主键幂等的同步骨架:
# 中心库增量同步:水位表记录上次同步时间,主键冲突则更新 import psycopg2, datetime WATERMARK_SQL = "SELECT last_ts FROM etl_watermark WHERE job_name=%s" UPSERT_SQL = """ INSERT INTO ods_meter_reading (meter_id, read_date, reading, sync_ts) VALUES (%s, %s, %s, now()) ON CONFLICT (meter_id, read_date) DO UPDATE SET reading = EXCLUDED.reading """ def sync(job="meter_reading", batch=5000): with psycopg2.connect(DSN) as conn, conn.cursor() as cur: cur.execute(WATERMARK_SQL, (job,)) last_ts = cur.fetchone()[0] cur.execute("""SELECT meter_id, read_date, reading FROM src_meter_reading WHERE update_time > %s ORDER BY update_time LIMIT %s""", (last_ts, batch)) rows = cur.fetchall() cur.executemany(UPSERT_SQL, rows) if rows: cur.execute("UPDATE etl_watermark SET last_ts=%s WHERE job_name=%s", (datetime.datetime.now(), job))ON CONFLICT DO UPDATE保证重跑不产生重复行,这是交换任务能安全重试的基础。batch设5000是折中值,太小同步慢,太大一次事务锁表时间长,影响营销系统白天的正常查询。水位表要单独维护,不能拿业务表的最大时间戳当水位,因为业务表存在补录和回退修改,update_time才是可靠依据。定时对账任务建议每小时跑一次,只比条数和关键字段哈希,不一致就告警而不是自动覆盖——自动覆盖在权属不清的系统间迟早出事。
3.2 企业级GIS:管网数据入库与空间分析
企业级GIS在方案里的定位是"海量数据统一管理、数据检测、数据更新、数据共享",服务生产运营、服务营销、综合管理三个体系。落地时它承担三类查询:地图展示、地图查询、空间分析。前两类是面子,第三类才是里子。
管网数据入库的顺序不能乱:先基础地形和影像做底图,再管段和节点,最后阀门、消火栓、监测点这些附属设施。拓扑关系必须建,管段首尾节点不连通,爆管分析就跑不出正确结果。空间索引一定要建,否则一个半径查询就能把库压死:
-- 爆管影响范围分析:以爆管点为圆心300米缓冲,找出受影响管段和需关闭阀门 CREATE INDEX idx_pipe_geom ON pipe_network USING GIST (geom); SELECT p.pipe_id, p.diameter, ST_Distance(p.geom::geography, b.geom::geography) AS dist_m FROM pipe_network p JOIN pipe_burst b ON b.id = :burst_id WHERE ST_DWithin(p.geom::geography, b.geom::geography, :radius_m) ORDER BY dist_m; -- 关阀方案:找缓冲范围内与爆管管段连通的阀门 SELECT v.valve_id, v.valve_type, v.operate_status FROM valve v WHERE v.operate_status = 0 -- 0表示可操作 AND ST_DWithin(v.geom::geography, :burst_geom, 300);ST_DWithin比先算距离再过滤快一个数量级,因为它能命中GIST索引。::geography把坐标转成地理坐标,距离单位才是米,直接用几何坐标算出来是度,现场按这个去关阀会闹笑话。radius_m不要写死,DN300以上大口径管段和末端小口径管段的关阀半径差别很大,通常按管径分档配置。
3.3 数字供水门户:组织、数据权限与功能权限的三层模型
方案对门户的描述集中在一点:集中管理组织结构、用户登录、数据权限分配、功能权限设置,保证所管理信息在各应用系统之间的一致性。这句话的工程含义是——门户必须做单点登录和统一权限,否则每个子系统一套账号,人员调动时运维会被追着改密码。
权限模型建议三层:功能权限(能看哪些菜单)、数据权限(能看哪些组织的数据)、操作权限(能改还是只能看)。数据权限最容易做错,常见做法是用组织树加数据范围类型:
-- 用户-角色-组织范围:data_scope 1本人 2本部门 3本部门及下级 4指定组织 5全部 CREATE TABLE sys_user_role ( user_id BIGINT NOT NULL, role_id BIGINT NOT NULL, data_scope SMALLINT DEFAULT 2, PRIMARY KEY (user_id, role_id) ); CREATE TABLE sys_role_org ( role_id BIGINT NOT NULL, org_id BIGINT NOT NULL, PRIMARY KEY (role_id, org_id) ); -- 查询某用户可见的抄表数据:按组织范围拼范围条件 SELECT m.meter_id, m.reading FROM ods_meter_reading m JOIN sys_org o ON o.org_id = m.org_id WHERE o.org_id IN ( SELECT org_id FROM sys_role_org WHERE role_id IN ( SELECT role_id FROM sys_user_role WHERE user_id = :uid ) );data_scope设2(本部门)是大多数水务公司的默认档,集团层面的分析岗给3或5。范围条件一定要下推到SQL,不要在应用层拉全量再过滤,用户基数上百、抄表数据上千万时,应用层过滤会把接口拖到超时。门户上线前建议做一次权限矩阵复核,把"谁能看全市管网压力"这种问题逐条确认,比上线后补权限便宜得多。
4. 三大业务体系的功能映射:生产运营、服务营销、综合管理如何拆到模块
方案把数字供水业务划成生产运营、服务营销、综合管理三大体系,这是功能清单的骨架,也是招投标时的报价单位。拆得好,工期可控;拆得糊,每个模块都要扯皮。下面按体系讲清每个模块的输入输出和依赖关系。
4.1 生产运营体系:六类监测点的采集频率与告警策略
方案里生产运营体系包含供水生产调度平台、设施巡检、供水管网系统、三维可视化、应急指挥调度、动态水力模型,其中生产调度平台明确列了压力监测、流量监测、厂站监测、水质监测、二次供水、安保视频监测六类。这六类的采集频率和阈值不能一刀切:
| 监测项 | 采样频率 | 上报周期 | 告警阈值示例 | 备注 |
|---|---|---|---|---|
| 管网压力 | 5秒 | 1分钟 | 低于0.15MPa或高于0.60MPa | 按DMA分区上下限配置 |
| 管网流量 | 10秒 | 1分钟 | 夜间最小流量超基线20% | 用于漏损定位 |
| 出厂水质 | 30秒 | 5分钟 | 余氯低于0.30mg/L | 在线仪自带质控 |
| 厂站运行 | 1秒 | 1分钟 | 泵组电流偏差超15% | 取自DCS/OPC UA |
| 二次供水 | 30秒 | 5分钟 | 出水压力低于设定值0.05MPa | 泵房数量大,注意并发 |
| 安保视频 | 事件触发 | 实时 | 移动侦测、越界 | 只推事件和在线状态 |
告警逻辑最忌讳来一个越限值就报一次。管网压力受用水高峰影响,单点越限每天能报上千条,运维直接屏蔽告警,系统就废了。常见做法是连续N点越限加持续时间双条件:
# 压力越限告警:连续3个采样点越限且持续≥60秒才触发,避免抖动误报 LIMIT_LOW, LIMIT_HIGH = 0.15, 0.60 HOLD_POINTS = 3 HOLD_SECONDS = 60 def check_alarm(point_id, samples): """samples: [(ts, value, quality), ...] 按时间升序,只取 quality=0 的点""" valid = [(t, v) for t, v, q in samples if q == 0] if len(valid) < HOLD_POINTS: return None # 数据不足,不告警 tail = valid[-HOLD_POINTS:] span = tail[-1][0] - tail[0][0] over = all(v < LIMIT_LOW or v > LIMIT_HIGH for _, v in tail) if over and span >= HOLD_SECONDS: level = 1 if abs(tail[-1][1] - (LIMIT_LOW + LIMIT_HIGH) / 2) < 0.1 else 2 return {"point_id": point_id, "level": level, "value": tail[-1][1]} return Nonequality == 0这个过滤条件是必须的,插补值和可疑值参与告警判断,会出现"设备没恢复但告警自动消除"的情况。HOLD_POINTS和HOLD_SECONDS两个条件同时满足才报,前者防毛刺,后者防瞬时波动。告警等级按偏离基准的幅度分档,低压区(管网末端、高楼层)和高压区(泵后)不能用同一套阈值,所以阈值配置要挂到DMA分区而不是全局。
水力模型和优化调度的依赖关系也要提前理清:动态水力模型需要管网拓扑、管径、糙率、节点流量,节点流量又来自营销抄表数据和DMA计量。数据和模型不同步是这类项目最典型的延期原因——模型建好了,抄表数据粒度是一个月一次,模型只能当摆设。常见折中方案是先用DMA总流量做节点分配,模型精度按周校核,等计量改造完成后逐步细化。
4.2 服务营销体系:营销、客服、热线与计量数据的闭环
服务营销体系包含客户服务管理、供水营销管理、供水服务热线。这三块在方案里是并列的,实际落地时它们的耦合点在工单和计量数据上:热线产生投诉工单,工单可能转成换表或维修,换表又会影响营销的计量周期。
闭环的关键在于工单状态机要统一。热线系统、客服系统、巡检系统各自维护工单状态,用户打第二次电话时客服看到的是"已处理",现场人员看的是"待派工",这类事故在供水企业很常见。做法是把工单主表放在综合管理体系的工程管理模块或独立工单中心,各渠道只做创建和查询,状态流转集中在一处。计量数据的接入同理,换表当天的旧表止度和新表起度要有明确规则,否则当月账单会出现用量突增,热线话务量直接翻倍。
4.3 综合管理体系:设备资产、工程管理闭环与移动办公
综合管理体系包括移动办公、决策分析、设备管理、工程管理。方案对工程管理的描述是"项目计划、执行、监控的闭环管理,实现项目全生命周期贯通",这句话落到系统上就是三张表:项目主表、里程碑表、变更记录表。
设备管理和生产运营的联动点在线性资产台账。阀门、流量计、压力计这些设备的生产厂家、口径、安装位置、检定日期,既要服务于检修计划,也要服务于GIS的空间展示和爆管关阀分析。所以设施资源库的台账主键要和GIS里的设施编码一致,两套编码是常见的坑——GIS里叫"阀-0123",资产系统里叫"V0123",对不上就只能人工核。移动办公则要控制范围,把巡检、工单、抄表、审批做成App就够了,不要试图把调度也搬到手机上,现场信号和操作精度都不支持。
5. 漏损率与产销差分析的调参与排错
漏损率是智慧供水最难算准、也最容易被质疑的一个指标,因为它的输入横跨营销的售水量、调度的供水量、DMA的计量流量三套数据,任何一套的口径不一致,结果就会差出几个百分点。
先看数据对齐这一关。产销差 = 供水量 − 售水量,看似简单,但供水量通常来自出厂流量计的日累计值,售水量来自抄表系统的账单周期,两者时间窗口根本不一样。抄表日分散在全月,账单周期可能是25天也可能是35天,直接相减没有意义。我的做法是先把抄表数据按日摊平:用上一周期和本周期的读数差除以实际天数,得到日均售水量,再和供水量的日累计做同期对齐。
-- 把抄表周期用量摊平到日,再与供水量按日对齐算产销差 WITH daily_sold AS ( SELECT meter_id, d::date AS stat_date, (reading - prev_reading)::numeric / NULLIF((read_date - prev_read_date), 0) AS daily_vol FROM meter_reading mr, LATERAL generate_series(prev_read_date + 1, read_date, '1 day') AS d WHERE reading >= prev_reading -- 负数多为换表或抄错,先剔除 ) SELECT s.stat_date, SUM(s.daily_vol) AS sold_m3, SUM(g.supply_m3) AS supply_m3, ROUND((SUM(g.supply_m3) - SUM(s.daily_vol)) / NULLIF(SUM(g.supply_m3), 0) * 100, 2) AS loss_pct FROM daily_sold s JOIN ods_daily_supply g ON g.stat_date = s.stat_date GROUP BY s.stat_date ORDER BY s.stat_date;reading >= prev_reading这个条件看着粗暴,但能过滤掉换表、抄错、表倒走三类脏数据,这几类数据占异常总量的大头。NULLIF防除零,摊平天数为0的记录直接置空而不是报错,让整批任务能跑完。真正的坑在最后一步:如果把换表当天的读数差当成正常用量摊平,那一天的分区产销差会跳十几个点,所以换表记录要从台账里单独关联出来,按新表起度重算。
DMA分区的最小夜间流量法是定位漏损点的主力方法,参数调节有三个要点。第一,时间窗口取凌晨2:00到4:00,这段时间居民用水基本停歇;第二,要先剔除窗口内压力低于0.15MPa的记录,压力低时流量自然小,会把漏损量算低;第三,基线不是固定值,要按分区用户数、管长和季节滚动更新,通常取前30天同期夜间流量的中位数,用均值会被个别高值拉偏。指标上看两个:夜间最小流量与日均流量的比值,以及夜间流量连续7天上升的趋势,前者判漏损水平,后者判新增漏点。
最后是数据质量排查,绝大多数"漏损率异常"最后都查成采集问题而不是真漏。巡检脚本建议覆盖三类检查:测点在线率和心跳间隔是否超过3倍上报周期;流量计的正负累积是否出现回退;同一DMA的进水流量与各分支流量之和的偏差是否超过5%。这三项跑完,剩下的数才值得拿去做漏损分析。
本文还有配套的精品资源,点击获取