Skip to main content

industrial-aiops-energy — 能源 edition (变电 / 电力)

The energy edition of Industrial-AIOps, split out into its own repo: read-only OT connectors for substation / utility telecontrol protocols, built on top of iaiops.core.

  • IEC 60870-5-104 (c104) — RTU / substation telemetry
  • DNP3 / IEEE 1815 (pydnp3) — outstation monitoring
  • IEC 61850 MMS (pyiec61850, linux-only wheel) — substation IED reads

It reuses the base package's shared governance (audit / budget / risk-tier / undo), cross-protocol brain (data-flow / alarm / OEE / downtime RCA on the normalized ISA-95/18.2 model), and MCP server infrastructure — this repo only adds the three energy connectors + their session builders + MCP tools. Read-first: no control-direction writes are exposed.

Current release: 0.1.11 (requires iaiops>=0.20.3,<1.0). New in 0.1.11 — all three monitor paths are CI-gated for the first time, and a skipped live test now fails the build instead of passing it. DNP3 was the holdout: pip install pydnp3 fails on any current Linux, so this repo inherited the ecosystem's "unbuildable on hosted runners" and tests/test_dnp3_live.py skipped on every build. It is not unbuildable — opendnp3 compiles clean, and the 2019 binding layer needed three mechanical fixes, now scripted in scripts/build_pydnp3.sh and running on real GitHub runners. Also inherits two governance fixes from iaiops 0.20.3 (pin raised): a call that failed is no longer audited as a success (which also mis-informed the pattern circuit breaker on every failure), and the runaway guard can now see a caller retrying a denial forever. Previously in 0.1.10 — a security fix inherited from the base package: three egress tools this edition mirrors (stream_publish, stream_publish_event, historian_push) wrote their credential — a NATS auth token, a TSDB password — into the audit log in the clear, and audit_forward shipped that row to the configured SIEM. They are defined in iaiops, so this edition could not fix it alone; the pin moves to iaiops>=0.20.2, and a contract test now fails the build if the whole registered surface ever again carries an undeclared credential parameter. If you have passed a token or historian password to these tools, rotate it and check existing audit rows. The energy connectors themselves take no credential parameters. Previously in 0.1.9 — every tool ships the MCP ToolAnnotations hints (readOnlyHint / destructiveHint / openWorldHint), derived from the @governed_tool harness rather than hand-written, so a client can tell a monitor read from a tool that acts without parsing the [READ]/[WRITE] docstring tag. On the wire that is 59 tools, 55 read-only and 0 destructive — this edition exposes no control direction, and that is now enforced by a test rather than only documented. They are hints, not a gate: the MCP spec forbids relying on annotations for security decisions, and enforcement stays in @governed_tool. The base pin moved to iaiops>=0.20.1 so the hint derivation is imported from mcp_server.hints instead of duplicated here.

Previously in 0.1.8 — the base IAIOPS_READ_ONLY gate was removed in iaiops 0.19.0 (read/write authorisation is the caller's decision — agent judgement / account management — not the tap's; every tool is governed and audited via the base @governed_tool harness), so this edition drops it too. It keeps the IAIOPS_NO_EGRESS=1 gate — a data-exfiltration / airgap axis that withholds data-shipping tools from list_tools() at registration time. This edition runs its own FastMCP instance, so the gate is wired into its own main(); without it IAIOPS_NO_EGRESS=1 would still expose historian_push, rca_narrate and the stream_publish* pair mirrored in from the base brain. The energy connectors themselves are monitor-only and survive the gate intact. See CHANGELOG.md.

Previously in 0.1.6 — an audit-hardening pass over the three read-only connectors: DNP3 no longer reports an offline outstation as online or returns a partial integrity-poll database; IEC-61850 gained a bounded connect/request timeout and stopped fabricating 0.0/empty-success on failure; the substation analyzer no longer calls a lone breaker-open a "selective trip"; tests isolate IAIOPS_HOME; and the base pin was raised to iaiops>=0.14 so the governance endpoint-scoping fix applies. See CHANGELOG.md §0.1.6. (0.1.5 verified the IEC-104 monitor path — a real c104 client↔server round-trip in a Linux container, tests/test_iec104_live.py.) Physical RTU/IED still 待核实. Since 0.1.3 the server has its own MCP identityiaiops-energy-mcp runs a dedicated FastMCP("iaiops-energy") instance with energy-specific instructions (IEC-104 / DNP3 / IEC-61850, read-first, no control/operate), with the base cross-protocol brain tools mirrored onto it — plus an edition skill (skills/iaiops-energy/SKILL.md, anti-drift-tested against the registered tool surface) and protocol-consistency contract tests (every tool must carry the governance marker, a [READ]-style risk tag, an Args: section, and the canonical {error, hint} error shape; the server refuses to start if any registered tool lacks the governance marker).

🧪 测试与共创 / Beta testing & co-creation

变电站现场的测试反馈是这个包最缺的东西。 IEC-104 / DNP3 / IEC-61850 三条监视路径均已 对真实库(c104 / opendnp3 / libiec61850 的进程内 server)loopback 往返验证,且三条都在每次 CI 真实执行——跳过会让构建失败,而不是让它变绿。(2026-08-01 起:此前 DNP3 的证据只是 2026-07-02 的一次手工运行,因为 pydnp3 被认为在托管 runner 上无法构建;那个结论是错的, 见下方 scripts/build_pydnp3.sh。)但 真实 RTU / IED 物理设备一律 待核实 —— 如果你能在授权的测试环境里对真实变电设备跑一遍 iaiops doctor,我们非常想听结果。 经你验证的设备会署名写进支持矩阵。

Live substation RTU / IED / IEC-104 field testing is what this package needs most. The IEC-104, DNP3 and IEC-61850 monitor paths are library-loopback-verified, and all three now run on every CI build — a skip fails the build rather than passing it. (Since 2026-08-01: DNP3's evidence used to be a single manual run on 2026-07-02, because pydnp3 was believed unbuildable on hosted runners. That belief was wrong — see scripts/build_pydnp3.sh.) Real gear stays 待核实. Report results (protocol + device model + iaiops doctor output) via the base repo's pinned issue: 👉 industrial-aiops#28 — Call for field-testing partners (v0.10.0)

Why a separate repo

Energy targets a distinct buyer (utilities / substations), has heavier platform-specific deps (pyiec61850 is a linux-only SWIG wheel; pydnp3 builds a native ext), and its own compliance surface (电力监控系统安全防护). Splitting keeps the base install light. See the base repo's docs/ENERGY-SPINOUT.md for the plan.

Install

pip install iaiops-energy[energy]      # all three energy protocols
pip install iaiops-energy[iec104]      # just IEC-104

iaiops-energy pulls in iaiops (the shared core) automatically.

Use (MCP)

iaiops-energy-mcp                       # brain + energy tools over stdio

Point a target at your substation gear in ~/.iaiops/config.yaml (protocol: iec104|dnp3|iec61850, host, port, common_address / unit_id).

Edge deployment & ecosystem (edge-native / Margo)

Like the base package, the energy edition rides on a hardened, centrally-managed edge host as a portable, governed edge application — mapping onto the Margo edge-interoperability roles (immutable host · compliant orchestrator · iaiops-energy = the OT-domain app), deployable as an OCI Managed Container (outbound-only to substation RTUs/IEDs, no inbound). A container + margo.org/v1-alpha1 application-description skeleton is in deploy/margo/; the full alignment + honest gap analysis lives in the base repo's docs/MARGO-ALIGNMENT.md. The descriptor is validated against Margo's published margo.org/v1-alpha1 LinkML schema on every PR (CI job margo-descriptor) and passes clean — structural validity only, see deploy/margo/schema/PROVENANCE.md.

Honest status: a natural Margo edge application, but NOT Margo-compliant yet — image build, hosted+signed package, and a published conformance result are roadmap . No claim of compliance until that result exists, and the schema pass above is not a step toward it: the compliance test suite cannot be run today because it does not exist yet (no conformance repo in the margo org; a first PR1 vertical slice was still being scoped as of 2026-01-15).

Validation status (honest)

The same honesty ladder as the base repo. Driver codec / API surface is verified against the real libraries; the mock/monkeypatched unit tests run in CI without hardware. See the base repo's docs/PREVIEW-VERIFICATION.md runbook for how a protocol is promoted.

Protocol Status CI coverage Evidence
DNP3 / IEEE 1815 verified (monitor path) ✅ runs every push ¹ Real master↔outstation round-trip against a live opendnp3 outstation (pydnp3): is_online() reflects the real channel OnStateChange, and integrity_poll() (Class 0/1/2/3) returns the seeded binary/analog/counter database grouped by type. See tests/test_dnp3_live.py (@pytest.mark.integration). No physical RTU.
IEC 60870-5-104 verified (monitor path) ✅ runs every push Real client↔server round-trip against an in-process c104 server (tests/test_iec104_live.py + tests/iec104_server_harness.py, @pytest.mark.integration, passes in a Linux container): iec104_connection_info discovers the seeded station, iec104_interrogate (general interrogation / C_IC) returns the seeded M_ME_NC_1 + M_SP_NA_1 points with quality, iec104_read_point reads the measurand, a bad IOA yields found=False with no fabricated value, and server-side ASDU capture proves no control ASDU (C_SC / C_DC / C_SE) is ever issued. c104 ships no macOS wheel so the test skips on macOS (runs in CI / Linux). No physical RTU. Monitor/read only.
IEC 61850 (MMS) verified (monitor path) ✅ runs every push Real client↔server MMS round-trip against an in-process libiec61850 MMS server built with pyiec61850's server API: iec61850_device_directory lists the logical device (and browses its logical nodes / data objects), and iec61850_read returns a seeded measurand (TotW.mag.f, FC MX) over real ISO-on-TCP; a bad reference surfaces an MMS data-access error instead of a fabricated value. See tests/test_iec61850_live.py (@pytest.mark.integration, skips when pyiec61850 / its server API is absent). No physical IED. Read/monitor only — control / GOOSE / SV out of scope.

¹ All three monitor paths are now CI-gated, and a skip fails the build rather than passing it (no live protocol test may skip). This used to read: "only IEC-104 is CI-gated; DNP3 and IEC-61850 rest on out-of-CI runs, not on the green badge." That was true and is no longer.

DNP3 was the last one, and the reason is worth recording because the old note here — and the CI job, and this README — all repeated the same wrong conclusion for months: pip install pydnp3 fails on any current Linux, so it was taken as unbuildable on hosted runners. It is not. opendnp3 itself compiles clean; what had rotted was the 2019 binding layer. Three mechanical fixes, no patches to opendnp3:

  1. Python headers must be present (python3-dev) — without them the build dies at Python.h: No such file or directory, which is what "unbuildable" looked like;
  2. 214 vendored headers #include <python2.7/Python.h>, rewritten to <Python.h>;
  3. the vendored pybind11 predates CPython 3.11 (it reads PyFrameObject internals that 3.11 made opaque) and GCC 13 (std::uint16_t without <cstdint>) — replaced with pybind11 v2.13.6.

scripts/build_pydnp3.sh applies all three and verifies the import. ~3 min cold on two cores. The lesson generalises: "the ecosystem says it cannot be built" is a claim to test, not to inherit.

DNP3 notes: read-only / monitor direction only (no control). Its DNP3Manager.Shutdown() can block in a long-lived interpreter, so the connector bounds teardown (_Pydnp3MasterAdapter.shutdown) and the test drives the round-trip in a short-lived child process.

License

MIT — © wei. Part of the vendor-neutral, governed Industrial-AIOps line.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

iaiops_energy-0.1.11.tar.gz (152.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

iaiops_energy-0.1.11-py3-none-any.whl (49.9 kB view details)

Uploaded Python 3

File details

Details for the file iaiops_energy-0.1.11.tar.gz.

File metadata

  • Download URL: iaiops_energy-0.1.11.tar.gz
  • Upload date:
  • Size: 152.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.12

File hashes

Hashes for iaiops_energy-0.1.11.tar.gz
Algorithm Hash digest
SHA256 83f1df763c9121b065d6e51342acccc336794282c482918192ffe0a6aab2a657
MD5 4a6a7fba5771b1450bddb3be88f5e981
BLAKE2b-256 19bc2c1bffa8deefc3dc0d9212ead1d594df94b98d3109212ae1c7e59c90c0d3

See more details on using hashes here.

File details

Details for the file iaiops_energy-0.1.11-py3-none-any.whl.

File metadata

  • Download URL: iaiops_energy-0.1.11-py3-none-any.whl
  • Upload date:
  • Size: 49.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.12

File hashes

Hashes for iaiops_energy-0.1.11-py3-none-any.whl
Algorithm Hash digest
SHA256 708b1834f1e4dcaef72c8f84d5adbbb606f7c55a71ae6109e7b33852bacffb0e
MD5 3d118e749f23810012d142de85ab406f
BLAKE2b-256 4d8b96485410f3f51cb62737c3520eb18d0bc930889297e97ef26db84ed8235e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page