Skip to content
Agentmart
Submit a tool

Industrial-AIOps

Governed OT data tap: 15 field protocols + cross-protocol RCA brain; audit + MOC gating.

Connector by industrial-aiops · GitHub account verified by the MCP Registry

IndexedMITLocal (stdio)★ 7
Write a review

Install

Works with Claude Code, Codex, VS Code, Cursor, Windsurf, Claude Desktop. Read the repository before you give any tool access to your data.

npx agentmarket install connector/industrial-aiops-iaiops

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Governed OT data tap: 15 field protocols + cross-protocol RCA brain; audit + MOC gating.

Use cases: monitoring-observability, incident-response

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this server can do and what it asks for, from its tool list, install config and code. Checked Oct 25, 2026.

Tools
180 read · 25 write · 0 delete
Secrets
1 (API keys, tokens or passwords)
Install scripts
None found
Runs as
Python package

Tools by what they do 205

Read from the source code; the running server may list different tools.

Read 180 · Look things up without changing anything.

  • adopt_alias_map
  • alarm_bad_actors
  • alarm_cascade
  • alarm_event_clusters
  • alarm_flood_analysis
  • alarm_rationalization_worksheet
  • anomaly_scan
  • asset_inventory
  • bacnet_discover
  • bacnet_object_list
  • bacnet_read_points
  • bacnet_read_property
Show 168 more tools
  • bacnet_read_trend_log
  • bas_alarm_list
  • bas_point_list
  • bas_point_read
  • bas_trend_read
  • baseline_check
  • baseline_check_in_context
  • baseline_learn
  • baseline_learn_contextual
  • baseline_status
  • changeover_analysis
  • cleanroom_particle_check
  • cleanroom_pressure_cascade
  • compliance_dengbao_levels
  • compliance_evidence_bundle
  • compliance_frameworks
  • compliance_mapping
  • compliance_report
  • control_loop_health
  • cross_protocol_asset_model
  • data_quality_fleet_rollup
  • data_quality_scorecard
  • defect_pareto
  • device_advisory_check
  • diagnose_dataflow
  • diff_alias_map
  • disinfection_ct
  • downtime_attribution
  • downtime_events
  • downtime_root_cause
  • downtime_root_cause_live
  • downtime_triage
  • economizer_check
  • eip_controller_info
  • eip_list_tags
  • eip_read_many
  • eip_read_tag
  • ethercat_master_state
  • ethercat_read_pdo
  • ethercat_read_sdo
  • ethercat_slave_info
  • ethercat_slaves
  • export_data
  • fins_cpu_info
  • fins_cpu_status
  • fins_read_bits
  • fins_read_many
  • fins_read_words
  • fleet_incidents
  • fleet_status
  • hart_burst_listen
  • hart_burst_sample
  • hart_device_identity
  • hart_dynamic_variables
  • hart_primary_variable
  • health_summary
  • heartbeat_health
  • heat_exchanger_fouling
  • historian_coverage
  • historian_health
  • historian_query
  • ignition_alarm_status
  • ignition_gateway_status
  • investigation_list
  • investigation_open
  • investigation_readiness
  • investigation_show
  • iolink_device_info
  • iolink_master_info
  • iolink_ports
  • iolink_read_isdu
  • iolink_read_pdin
  • iolink_scan
  • isolation_room_check
  • learn_cause_weights
  • line_bottleneck
  • line_relation_declare
  • line_relations_list
  • mc_cclink_link_read
  • mc_cclink_network_health
  • mc_cclink_templates
  • mc_cpu_status
  • mc_read_bits
  • mc_read_many
  • mc_read_words
  • mechanism_library_check
  • mechanism_library_list
  • medical_gas_check
  • meter_hh_check
  • meter_load_profile
  • modbus_detect_byte_order
  • modbus_health_summary
  • modbus_list_templates
  • modbus_read_coils
  • modbus_read_discrete
  • modbus_read_holding
  • modbus_read_input
  • monitor_changes
  • mqtt_read_topic
  • mtconnect_assets
  • mtconnect_current
  • mtconnect_oee_snapshot
  • mtconnect_probe
  • mtconnect_sample
  • oee_compute
  • oee_multidim
  • onboarding_status
  • opcua_alarm_events
  • opcua_anomaly_scan
  • opcua_browse
  • opcua_diagnose_connection
  • opcua_discover_tags
  • opcua_health_summary
  • opcua_read_alarms
  • opcua_read_history
  • opcua_read_many
  • opcua_read_node
  • opcua_server_info
  • or_environment_check
  • pdm_forecast
  • pharma_water_check
  • plc_program_drift
  • plc_program_history
  • plc_program_outline
  • plc_program_section
  • plc_program_snapshot
  • plc_program_visibility
  • plc_program_xref
  • plc_program_xref_config
  • profinet_asset_inventory
  • profinet_discover
  • profinet_identify_station
  • profinet_station_params
  • protocols_supported
  • pv_performance
  • rca_corpus_from_maintenance
  • rca_narrate
  • s7_cpu_info
  • s7_read_area
  • s7_read_db
  • s7_read_many
  • secsgem_equipment_status
  • secsgem_list_alarms
  • secsgem_list_equipment_constants
  • secsgem_list_process_programs
  • secsgem_list_status_variables
  • secsgem_read_equipment_constants
  • secsgem_read_status_variables
  • sensor_profile_check
  • sensor_profile_list
  • sensor_profile_show
  • sensor_read_channel
  • serial_sniff
  • site_readiness
  • sortation_health
  • sparkplug_decode_payload
  • sparkplug_live_schema
  • sparkplug_node_list
  • spc_check
  • subscription_health
  • uns_browse
  • uns_live_audit
  • uns_live_drift
  • uns_schema_drift
  • uns_topic_audit
  • verify_determinism
  • water_quality_compliance
  • zone_comfort

Write 25 · Create, change, send or run things.

  • bacnet_cov_subscribe
  • bacnet_write_property
  • bas_command
  • baseline_record_change
  • eip_write_tag
  • ethercat_set_state
  • ethercat_write_sdo
  • fins_write_words
  • historian_push
  • ignition_tag_browse
  • ignition_tag_history
  • ignition_tag_read
Show 13 more tools
  • mc_write_words
  • modbus_apply_template
  • mqtt_publish
  • onboarding_config_draft
  • opcua_subscribe_sample
  • profinet_dcp_set
  • s7_write_db
  • sensor_import_iodd
  • sparkplug_subscribe_sample
  • stream_publish
  • stream_publish_event
  • tag_health
  • uns_publish

Secrets and settings it asks for

Secrets: values you paste in that let it act as you.

  • IAIOPS_MASTER_PASSWORD

Other settings (environment variables or headers).

  • IAIOPS_CONFIG
  • IAIOPS_MCP
  • IAIOPS_NO_EGRESS

Network hosts it talks to 6

  • github.com · found in code
  • glama.ai · found in code
  • opcfoundation.org · found in code
  • schemas.mtconnect.org · found in code
  • specification.margo.org · found in code
  • w3id.org · found in code

Files it touches

  • /proc/net/arp
  • /tmp/compliance-report.md
  • /tmp/evidence.zip
  • /usr/sbin/arp
  • Your home directory (~)
  • ~/.iaiops
  • ~/.iaiops/approvals
  • ~/.iaiops/audit.db
  • ~/.iaiops/baselines.json
  • ~/.iaiops/config.yaml
  • ~/.iaiops/data.db
  • ~/.iaiops/plc/Line3_Conveyor.scl
  • ~/.iaiops/plc/Line3_today.scl
  • ~/.iaiops/plc/Line3.scl
  • ~/.iaiops/plc/OB1.awl
  • ~/.iaiops/rules.yaml
  • ~/.iaiops/secrets.enc
  • ~/.iaiops/undo.db
  • ~/.ot-aiops
  • ~/advisories.yaml
  • Any path the agent passes to its tools

Tools (205)

Read from the source code; the running server may differ. Descriptions are the server’s own words; hidden characters are shown as [U+…].

  • adopt_alias_map

    [READ][risk=low][PERSIST] Adopt + persist the canonical alias map for a site. Writes a local owner-only advisory JSON file (NOT an OT-device write — hence risk=low); see the persistence note below. Runs the cross-protocol asset model over ``feeds``, extracts the adopted map ``{canonical_alias: {ref, protocol, asset, name, class}}``, and persists it as the site's baseline (owner-only JSON under the iaiops home). Re-running overwrites the baseline. Advisory — the map is a SUGGESTION, never a server-side rename (OT-dangerous). Args: feeds: Per-protocol tag feeds ``[{protocol, source, asset…

  • alarm_bad_actors

    [READ][risk=low] ISA-18.2 alarm-flood analysis over a list of alarm events. Args: events: Alarm/condition events — {source, timestamp (ISO-8601), priority?, state? (ACTIVE/RTN/ACK)}. window_minutes: Analysis window; omitted → inferred from event timestamps. chatter_window_s: A source with >=3 transitions inside this window chatters. standing_s: An alarm active longer than this is 'standing/stale' (default 24h). top_n: How many top offenders to return. Returns dict: {event_count, window_minutes, alarms_per_hour, isa_18_2:{ok_max:6, manageable_max:12, flood_min:…

  • alarm_cascade

    [READ][risk=low] Collapse an alarm flood into cascades + each cascade's first-out root. Answers "which alarm to look at first" when 100+ alarms hit in minutes: groups annunciations into cascades (a new cascade starts after a quiet gap > window_s) and reports the FIRST-OUT alarm (earliest in the burst) as the likely root, plus downstream members and any chattering sources. First-out is a transparent heuristic cited by timestamp — NOT causal (use downtime_root_cause for causality). Pass 'events' for pure analysis, or an endpoint to collect live via the OPC-UA active-condition scan. Read-only; b…

  • alarm_event_clusters

    [READ][risk=low] Collapse ten phrasings of one fault into one row. `alarm_bad_actors` ranks by SOURCE, which answers "which instrument is noisiest" and not "which fault is noisiest". A plant that words one condition ten ways — `PT-101 HIGH`, `PT-102 HIGH`, `PT-103 high alarm` — gets ten bad actors and no sign that they are one problem, so a rationalization meeting works the list top-down and fixes the same thing three times. This groups the same events by what they SAY instead of by who said it. Clustering is **exact equality of a normalized string, not similarity**: case, punctuation and em…

  • alarm_flood_analysis

    [READ][risk=low] ISA-18.2 deep alarm-flood analysis: episodes + chattering + stale + advice. Deepens alarm_bad_actors: detects flood *episodes* (start/end/count/peak rate/ top contributors + each episode's first-out annunciation, per ISA-18.2's >=10 alarms per 10 min per operator), alarms chattering ACTIVE↔CLEARED, standing/ stale alarms, and percent-time-in-flood vs the ISA-18.2 targets (~1-2 alarms/ 10 min steady state, <1% time in flood). Also returns an ISA-18.2 'load_profile' (per-bucket rate band + peak period + trend) and per-source 'suppression_advice' (deadband/on-off-delay for chatt…

  • alarm_rationalization_worksheet

    [READ][risk=low] ISA-18.2 alarm-rationalization worksheet (CSV or inline rows). One row per alarm source, count-descending: count, % of total annunciations, chattering?, flood contributor?, and a recommendation stub — the starting document for an ISA-18.2 rationalization review. Pass 'events' for pure analysis, or an endpoint to collect live via the same OPC-UA active-condition scan the RCA copilot uses. With out_path the full worksheet is written as CSV and the path returned; otherwise bounded inline rows (truncation noted). Args: endpoint: Endpoint name from config (used only when even…

  • anomaly_scan

    [DEPRECATED → opcua_anomaly_scan][READ][risk=low] Statistical outlier scan. Samples a node over a bounded window and flags statistical outliers. Computes mean/stddev/min/max and flags samples outside mean ± sigma*stddev. Simple statistics only — no ML, no persisted model. Args: node_id: The OPC-UA node id to scan. endpoint: Endpoint name from config. samples: Max samples (capped server-side). interval_ms: Delay between samples in milliseconds. sigma: Outlier band width in standard deviations.

  • asset_inventory

    [READ][risk=low] Actively fingerprint endpoints into an asset register. Connects to each target with our own protocol client and reads its identity call (S7 CPU info, EtherNet/IP controller info, OPC-UA server build info, Modbus device identification FC43, Mitsubishi CPU type, MTConnect device model), aggregating vendor/model/firmware/serial per device. Honest scope: ACTIVE fingerprinting (we connect to each device), NOT passive SPAN/tap discovery. Only finds devices we are configured to reach. Args: endpoints: Endpoint names to fingerprint; omit to fingerprint ALL configured en…

  • bacnet_cov_subscribe

    [READ][risk=low] Bounded Change-of-Value capture for one BACnet object. Subscribes to the object's COV, collects up to max_notifications notifications OR until timeout_s elapses (whichever first), then always unsubscribes. Never an open subscription — both count and wall-clock are hard-capped. Args: address: BACnet device address (from bacnet_discover), e.g. '192.168.1.10'. object_type: BACnet object type, e.g. 'analogInput', 'binaryValue'. instance: Object instance number. max_notifications: Stop after this many notifications (capped, default 20). timeout_s: Stop after t…

  • bacnet_discover

    [READ][risk=low] Who-Is broadcast: discover BACnet devices on the local network. Args: endpoint: Endpoint name from config (protocol 'bacnet'); omit for default. Returns dict: {endpoint, local_interface, device_count, devices:[{device_id, address}]}. Example: bacnet_discover(endpoint="ahu-net").

  • bacnet_object_list

    [READ][risk=low] Read a device's object list (its BACnet points/objects). Args: address: BACnet device address (from bacnet_discover), e.g. '192.168.1.10'. device_id: BACnet device instance id (from bacnet_discover). endpoint: Endpoint name from config (protocol 'bacnet'). Returns dict: {endpoint, address, device_id, object_count, objects:[{object_type, instance}]}. Example: bacnet_object_list(address="192.168.1.10", device_id=1001, endpoint="ahu-net").

  • bacnet_read_points

    [READ][risk=low] Read presentValue of all monitor-relevant points of a device. Reads the object list, filters to analog/binary/multistate I/O/value objects, and reads each presentValue — the HVAC/facility snapshot. Args: address: BACnet device address (from bacnet_discover). device_id: BACnet device instance id (from bacnet_discover). endpoint: Endpoint name from config (protocol 'bacnet'). Returns dict: {endpoint, address, device_id, point_count, skipped_non_readable, points:[{object_type, instance, present_value}]}. Example: bacnet_read_points(address="192.168.1.10", devi…

  • bacnet_read_property

    [READ][risk=low] Read one property of one BACnet object (default presentValue). Args: address: BACnet device address, e.g. '192.168.1.10'. object_type: BACnet object type, e.g. 'analogInput', 'binaryValue'. instance: Object instance number. bacnet_property: Property to read (default 'presentValue'). endpoint: Endpoint name from config (protocol 'bacnet'). Returns dict: {endpoint, address, object_type, instance, property, value}. Example: bacnet_read_property(address="192.168.1.10", object_type="analogInput", instance=1, endpoint="ahu-net").

  • bacnet_read_trend_log

    [READ][risk=low] Read buffered records from a device's BACnet TrendLog object. A TrendLog object logs a point's value over time on the device itself; this reads its logBuffer with a single bounded ReadRange. Read-only historical trend. Args: address: BACnet device address (from bacnet_discover), e.g. '192.168.1.10'. instance: TrendLog object instance number (from bacnet_object_list). count: Maximum records to return (capped, default 100). newest_first: Return most-recent records first (default True). endpoint: Endpoint name from config (protocol 'bacnet'). Returns dict: …

  • bacnet_write_property

    [WRITE][risk=HIGH][MOC] Write ONE BACnet object property (off by default). OT-DANGEROUS. Defaults to dry_run=True (nothing written). Overriding a live building-control point (present-value, optionally at a BACnet priority 1..16, or relinquishing that priority) can move real HVAC/plant. Captures the BEFORE value (read-back) and records an undo descriptor. Set dry_run=False AND record an approver (OPCUA_AUDIT_APPROVED_BY) to apply. 未经授权勿对生产控制系统写入. Args: address: BACnet device address (from bacnet_discover), e.g. '192.168.1.10'. object_type: BACnet object type, e.g. 'analogOutput', 'bin…

Show 190 more tools
  • bas_alarm_list

    [READ][risk=low] Active alarms/events from a BAS controller (normalized). Args: base_url: Controller REST base URL. vendor: Controller dialect — 'metasys' or 'niagara'. secret_name: Secret-store key holding the bearer token (omit if none). verify_tls: Verify the controller's TLS certificate (default True). Passing False is refused unless the operator set IAIOPS_ALLOW_INSECURE_TLS=1. Returns dict: {vendor, base_url, alarm_count, alarms:[{id, name, priority, state, message, timestamp}]}. Example: bas_alarm_list(base_url="https://bms/api", vendor="niagara").

  • bas_command

    [WRITE][risk=HIGH][MOC] Command ONE BAS controller point (off by default). OT-DANGEROUS. REFUSES any life-safety point (fire/smoke/egress/pressurization) OUTRIGHT — before any network I/O. Defaults to dry_run=True (nothing written). Captures the BEFORE value (read-back) and records an undo descriptor so the change is reversible. Set dry_run=False AND record an approver (OPCUA_AUDIT_APPROVED_BY) to apply. 未经授权勿对生产控制系统写入. Args: base_url: Controller REST base URL. vendor: Controller dialect — 'metasys' or 'niagara'. point_id: Point id/href to command. value: Value to write (coer…

  • bas_point_list

    [READ][risk=low] List a BAS controller's points/objects (vendor-normalized). Talks to the vendor supervisory controller's REST API (above BACnet). The bearer token is resolved from the encrypted secret store by key name, never passed inline. Token-egress guard: with a secret set, base_url must point at an internal host (private IP / single-label / .local-style name) or a host the operator allowlisted via IAIOPS_TOKEN_EGRESS_HOSTS — public hosts are refused before any request (prevents stored-token exfiltration). Args: base_url: Controller REST base URL, e.g. 'https://bms-host/api'. v…

  • bas_point_read

    [READ][risk=low] Present value(s) for one or more BAS controller points. Args: base_url: Controller REST base URL. vendor: Controller dialect — 'metasys' or 'niagara'. point_ids: Point ids/hrefs to read (from bas_point_list). secret_name: Secret-store key holding the bearer token (omit if none). verify_tls: Verify the controller's TLS certificate (default True). Passing False is refused unless the operator set IAIOPS_ALLOW_INSECURE_TLS=1. Returns dict: {vendor, base_url, point_count, points:[{id, name, value, unit, status}]}. Example: bas_point_read(base_url=…

  • bas_trend_read

    [READ][risk=low] Historical trend samples for one BAS point (bounded). Args: base_url: Controller REST base URL. vendor: Controller dialect — 'metasys' or 'niagara'. point_id: Point id/href whose trend history to read. count: Max samples to return (1..5000, capped server-side). secret_name: Secret-store key holding the bearer token (omit if none). verify_tls: Verify the controller's TLS certificate (default True). Passing False is refused unless the operator set IAIOPS_ALLOW_INSECURE_TLS=1. Returns dict: {vendor, base_url, point_id, sample_count, samples:[…

  • baseline_check

    [READ][risk=low] Check recent local samples against the learned baseline. Reads the last window_s seconds from ~/.iaiops/data.db (no device I/O) and judges them against the stored band. Conservative by design: a violation is reported ONLY when values are beyond p1/p99 by more than 3×MAD AND sustained for >=3 consecutive samples — a single spike is never flagged. Every violation cites the baseline window (from/to ts, n samples), the band values, and the offending samples' timestamps/values. No stored baseline → an explicit no_baseline answer (never a guess). Bounded output (<=10 violations, <=…

  • baseline_check_in_context

    [READ][risk=low] Check readings against the band for ONE declared context. A reading whose context was never learned comes back `unknown_context` and stops there. It is **not** compared against the global band or the nearest one, and that refusal is the entire point of the tool: borrowing a band turns "we have never seen this regime" into "this regime is normal" — a silent pass, in the direction nobody reports. The response lists the contexts that do have bands so the gap is actionable. Otherwise the usual conservative rules apply: a violation needs values beyond the band by more than `margi…

  • baseline_learn

    [READ][risk=low] Learn a conservative per-tag normal band from local history. Source is ~/.iaiops/data.db — the local store written by historian_push(sink="sqlite") — NOT a live device read. Learns robust percentiles (p1/p99 + median/MAD, no ML) from the tag's own samples, segmented at the latest change recorded via baseline_record_change (the band reflects only the post-change regime). REFUSES with an explicit insufficient_data verdict (listing exactly what is missing) below 100 usable samples or under 24h of span — it never invents a band from thin data. On success the band is persisted to …

  • baseline_learn_contextual

    [READ][risk=low] Learn one conservative band per declared context, not one per tag. One band per tag is wrong the moment a tag has more than one normal. A dryer running recipe A at 180 °C and recipe B at 240 °C gets a band spanning both, after which neither regime can go wrong — the band is too wide to catch a real excursion and too mixed to mean anything. OT normal ranges move with shift, product/recipe, and start-up versus steady state. **The context is declared, never inferred** (D16). Each sample carries a label under `context_key`; nothing here guesses which shift a timestamp falls in o…

  • baseline_record_change

    [READ][risk=low] Record an operator change-log entry for a tag (local only). Writes ONLY local metadata (~/.iaiops/baselines.json, owner-only) — never an OT device write, hence risk=low. A recorded change (setpoint moved, valve replaced, probe swapped) marks a regime boundary: the next baseline_learn uses only samples AFTER the latest change, so the band never mixes pre-change and post-change behavior. This operator change log — not a black-box score — is what makes the baseline trustworthy. Args: tag: Tag whose process changed, e.g. 'line1.temp'. note: What changed (required), e.g. …

  • baseline_status

    [READ][risk=low] Baseline status for one tag, or a bounded listing of all. Read from the local store only (no history scan, no device I/O) and never guesses: 'no_baseline' (nothing learned, no refused attempt), 'learning' (last learn refused — still accumulating history), 'ok' (band learned, last check clean), 'violation' (last check flagged a sustained excursion). With no tag, lists every tracked tag (bounded to 100 entries). Args: tag: Optional tag name; omit to list all tracked tags. Returns dict: {tag, status, band?, baseline_window?, changes_recorded?, ...} for one tag, or {tra…

  • changeover_analysis

    [READ][risk=low] Changeover / SMED durations between products. Breaks out what OEE availability only aggregates: each changeover is the gap between the last good part of one product and the first good part of the next — the setup/adjustment time SMED shrinks. Measures every changeover, ranks the longest, and totals the lost time, worst-first, each duration cited by its two bounding timestamps. Pure analysis over readings you pass in (a good-part completion stream from the MES / PLC counters); read-only, advisory. Args: good_parts: [{timestamp (ISO-8601), product}] — one per good part, an…

  • cleanroom_particle_check

    [READ][risk=low] Grade airborne particle counts against the limits you supply. No compendial table is shipped, on purpose. The grade / state / size limits belong to the site's qualified specification at its compendial revision, and a transcription this repository cannot verify would decide whether a batch environment passed — with the flattering error, a limit set too loose, reading as "in specification". A missing entry is reported as `no_limit` and named, never skipped and never assumed to pass. Args: samples: [{room, grade, state ('at_rest'|'in_operation'), particles_per_m3: {…

  • cleanroom_pressure_cascade

    [READ][risk=low] Grade a GMP cleanroom pressure cascade door by door (EU GMP Annex 1). The question a suite of classified rooms actually poses is not "is this room negative enough" — that is the isolation-room check — but **does the cascade hold from A down to D**: every door between differently classified areas has to push from the cleaner side to the dirtier one, and the chain is only as good as its weakest door. It is what an Annex 1 inspection walks, and the failure is silent (a door propped, a supply fan drifting) until an environmental-monitoring excursion turns up days later. Adjacenc…

  • compliance_dengbao_levels

    [READ][risk=low] 等保 2.0 二级 vs 三级 per-pillar deltas + honest iaiops posture. 等保 2.0 (GB/T 22239) is graded — the same control tightens as the level rises. Per governance pillar this shows the 二级 baseline, what 三级 additionally requires, and how far iaiops moves you toward it (with the honest per-control status/gap). An onboarding/self-assessment aid, NOT a certification. Args: level: Focus on one level — 'l2'/'l3', '二级'/'三级', or '2'/'3'. Omit for both. Returns dict: {framework, levels:[{id,name,note}], selected_level, pillar_count, deltas:[{pillar, l2_requires?, l3_adds?, iaiops, iaio…

  • compliance_evidence_bundle

    [READ][risk=low] Export the audit-evidence bundle (zip) for an auditor. Packages the governance evidence trail into one deterministic zip: audit_rows.jsonl (secrets already redacted upstream), chain_verification.json (SHA-256 hash-chain walk result), rules.yaml (if present), doctor_summary.json (non-probing config/secret-store facts), and manifest.json. Path is validated (no '..' traversal; parent created 0700). Args: out_path: Destination zip path (must end in .zip). since: Optional ISO-8601 floor on the audit row timestamp (inclusive). until: Optional ISO-8601 ceiling on the au…

  • compliance_frameworks

    [READ][risk=low] 跨框架对照: 防护指南 ↔ 等保 2.0 ↔ IEC 62443 ↔ GxP ↔ NIS2 ↔ CRA. Omit ``framework`` for one row per governance pillar: the matching 《防护指南》 requirement, 等保 2.0 control class, IEC 62443 FR, GxP clause, the NIS2 / CRA item refs that cite the pillar, and the iaiops status. Pass framework="nis2" (Directive (EU) 2022/2555 Art. 21(2)(a)-(j)) or "cra" (Regulation (EU) 2024/2847 Annex I) for that text item by item, each with an honest coverage: product_evidence (a cited, code-anchored mechanism produces relevant evidence — never "the measure is met"), gap, or organisational (product provides no e…

  • compliance_mapping

    [READ][risk=low] 《工控系统网络安全防护指南》 ↔ iaiops governance mapping. An honest onboarding/sales self-assessment across the pillars 分区隔离 / 可审计 / 双向认证 / 最小权限 / 数据保护 / 自主可控. Each control names how iaiops addresses it, an honest status (addressed / partial / 待核实), and the remaining gap. Returns dict: {framework, frameworks[], pillars[], control_count, status_summary {addressed, partial, 待核实}, controls:[{pillar, requirement, iaiops, status, gap, crosswalk{dengbao, iec62443}}]}. See compliance_frameworks for the full cross-framework 对照. Example: compliance_mapping().

  • compliance_report

    [READ][risk=low] Render the 等保 2.0 / IEC 62443 or NIS2 / CRA report (Markdown). Turns the compliance crosswalk into a deliverable document a CISO can read: title-page metadata (site / date / iaiops version), per-pillar 等保 L2/L3 status table, IEC 62443 FR1–6 crosswalk, honest gap list, and a governance-controls appendix (audit hash chain / approval tokens / dry-run+undo / mTLS). With framework='nis2' / 'cra' / 'eu' it renders instead the English NIS2 Art. 21 / CRA Annex I self-assessment (product evidence and gaps, organisational measures separated, cited mechanisms with code anchors). An onbo…

  • control_loop_health

    [READ][risk=low] Triage a PID control loop from a PV/SP/OP capture. Is the loop actually controlling? Over a short capture it flags the three classic misbehaviours — oscillation (PV crossing SP repeatedly), sustained offset (PV sitting away from SP), and output saturation (OP pinned at 0/100 %). Returns the mean offset, the error-crossing oscillation index, the OP saturation fractions, and a worst-wins verdict. Not a tuner — it triages which loops need a look. Pure analysis over readings you pass in; read-only. Args: samples: [{pv, sp, op?}] — process value, setpoint, controller output. …

  • cross_protocol_asset_model

    [READ][risk=low] Fuse per-protocol tag feeds into ONE unified asset model. Unifies the two per-protocol tag models (OPC-UA address-space discovery + Modbus register templates) into one cross-protocol asset/tag/alias model. Tags are re-classified with the SAME semantic classifier the OPC-UA layer uses, grouped into assets ACROSS protocols (a ``Line1`` OPC-UA folder + a ``Line1`` Modbus block become one asset), and each gets a canonical alias ``<site>.<asset>.<class_or_name>``. Advisory only — aliases are SUGGESTIONS, never a server-side rename (OT-dangerous). Args: feeds: List of per-prot…

  • data_quality_fleet_rollup

    [READ][risk=low] Cross-endpoint fleet rollup of data-TRUST: worst tags + bad quality. Builds on data_quality_scorecard to give a fleet-wide view: endpoints ranked by their single worst tag, bad-quality tag counts aggregated across every endpoint, and a first-class liveness rollup (dead-heartbeat / flatline). Staleness and gap budgets are configurable per tag (staleness_s / gap_threshold_s) and per feed, so a slow daily counter is not judged like a 1Hz sensor. Pure analysis. Args: feeds: Per-endpoint feeds — {endpoint, staleness_s?, tags:[{ref, label?, samples:[scalars or {value, …

  • data_quality_scorecard

    [READ][risk=low] Fleet data-TRUST scorecard across endpoints' tag feeds. Scores each tag 0-100 on whether its data can be BELIEVED — staleness, dead heartbeat, bad-quality, flatline, gaps, anomaly — then rolls up per endpoint and across the fleet. NOT process health (it does not score whether a value is alarming, only whether it is trustworthy). Pure analysis over provided feeds. Args: feeds: Per-endpoint feeds — {endpoint, tags:[{ref, label?, samples:[scalars or {value, good|quality, timestamp?}], expected_update_s?, heartbeat?}]}. default_staleness_s: Max sample-age before …

  • defect_pareto

    [READ][risk=low] Rank defect categories by count and mark the vital few (Pareto). The quality follow-on to an SPC signal: which defect categories drive most of the loss? Ranks categories by count, computes each one's share and the running cumulative share, and marks the vital few that reach the 80% line — where containment and CI effort has the most leverage. Pure analysis over records you pass in (an inspection / defect log); read-only, each share cited by its count. Args: defects: [{category, count?}] — with count the rows aggregate by category (summing); without it each row co…

  • device_advisory_check

    [READ][risk=low] Which scanned devices fall inside a mounted advisory's stated range. `iaiops scan` already reads vendor / model / firmware / serial and then does nothing with them. This closes that loop — and deliberately stops short of where a vulnerability scanner would go. **It reports that a device falls inside an advisory's stated range. Nothing more.** Not "vulnerable", not "exploitable", no severity score. Whether a published issue is reachable on a particular machine depends on configuration, network position and compensating controls that a read-only scan cannot see — and in OT mos…

  • diagnose_dataflow

    [READ][risk=low] Localize a 'no data' break across an endpoint's reachable hops. Probes connect → read(ref) → freshness → variance and returns a verdict with per-hop detail and a recommended action. The #1 OT triage: distinguishes "cannot connect" (network/PLC down) from "comms OK but value stale" (upstream/field/source) from "good status but flatline" (sensor stuck). Args: endpoint: Endpoint name from config (any protocol). ref: Tag/node/address/device to read (OPC-UA node id, Modbus address, S7 address string, MELSEC device). Omit to test connectivity only. freshness_th…

  • diff_alias_map

    [READ][risk=low] Diff a fresh discovery run against the adopted baseline. Loads the site's previously adopted alias map, re-runs the cross-protocol asset model over ``feeds``, and reports how the address space moved: tags added / removed / renamed (same ref, new alias) / reclassified (same ref+alias, new semantic class), plus a stable|changed verdict. Adopt a baseline first with ``adopt_alias_map``. Args: feeds: Fresh per-protocol tag feeds (same shape as adopt_alias_map). site: Site label whose baseline to diff against. Default 'site'. Returns dict: {site, verdict, counts:{added,re…

  • disinfection_ct

    [READ][risk=low] Achieved CT vs required CT per contact basin (SWTR disinfection). The water-treatment disinfection-credit calc: CT = free-chlorine residual (mg/L) × effective (T10) contact time (min). Each basin's achieved CT is compared to the required CT for the target log-inactivation — which the utility looks up from its state CT tables (temperature / pH / disinfectant specific) and passes in. Returns per-basin CT ratios worst-first and whether every basin meets its credit. Pure analysis over readings you pass in; read-only, advisory. Does NOT embed the CT tables — supply required_ct. A…

  • downtime_attribution

    [READ][risk=low] Which stoppage started it, and which ones were downstream of it. RCA weights evidence by TIME alone — a signal before onset counts, one after counts less. That is the honest half of the axis. Run `downtime_root_cause` per asset after one upstream stop and every downstream machine comes back with its own confident local root cause: each internally consistent, each citing real signals, and all but one about a machine that stopped because it was starved. The distinguishing fact is not in the evidence — it is the line's topology. Two rules decide an attribution and both must hol…

  • downtime_events

    [READ][risk=low] Detect running→stopped transitions and categorize stoppages. Args: series: Timestamped samples — {timestamp (ISO-8601), state} where state is a string (RUNNING/IDLE/FAULT…), a bool, or a number. category_map: Optional {state_label: category} override (else keyword heuristics map to changeover/material/mechanical/quality/break/unknown). min_duration_s: Ignore stoppages shorter than this (seconds). Returns dict: {samples, event_count, total_downtime_s, by_category:{cat: {count, downtime_s}}, events:[{start, end, duration_s, state, category}]}. …

  • downtime_root_cause

    [READ][risk=low] AI downtime root-cause copilot — cited verdict, ADVISORY only. Correlates whatever evidence you supply around a downtime/incident window — alarm events, tag samples, a diagnose_dataflow verdict, a machine-state series — ranks candidate root causes, and cites the REAL signals behind each. Read-first: it proposes a human-approved, undoable (MOC-gated) action but executes nothing. Anti-hallucination: only signals present in the input are cited; thin evidence downgrades to 'insufficient_evidence' with a 'recommended_next_data' list rather than a confident guess. Confidence combin…

  • downtime_root_cause_live

    [READ][risk=low] AI downtime RCA copilot that GATHERS its own live evidence. Same advisory, read-only, evidence-cited contract as downtime_root_cause — but instead of hand-injecting evidence you give an endpoint + incident window and it pulls the evidence itself: a cross-protocol diagnose_dataflow probe, a short sampled series per ref (so flatline/bad-quality/anomaly surface via tag_health), and active OPC-UA conditions. Light read load; non-destructive; nothing executed. The gathered bundle is echoed under 'collected_evidence' (no hidden inputs). Args: endpoint: Endpoint name from confi…

  • downtime_triage

    [READ][risk=low] One-call downtime triage: first-look alarm + RCA cause + precursors. Answers the operator's three simultaneous questions on a stopped line — which alarm to look at first, the likely cause, and whether anything warned us — then cross-checks whether the first-out alarm agrees with the RCA verdict. Composes alarm_cascade + downtime_root_cause + pdm_forecast over ONE incident; every field traces to a sub-report echoed under 'cascade'/'rca'/ 'precursor_forecasts'. Read-first and advisory: it proposes but executes nothing. Thin evidence downgrades honestly rather than guessing. Ar…

  • economizer_check

    [READ][risk=low] Air-handler economizer fault detection (building energy FDD). Is each AHU using free cooling when it can, and not fighting itself? Flags simultaneous heat/cool (both on = waste), not-economizing (outside air cool enough for free cooling but the OA damper is at minimum while mechanical cooling runs), and economizing-when-locked-out (OAT above the high limit but the damper wide open, dragging hot air in). Worst-first, each fault citing the temperatures/states behind it. Pure analysis over readings you pass in (BACnet AI/BI points); read-only, advisory. Args: units: [{ahu, …

  • eip_controller_info

    [READ][risk=low] Controller identity (proves the CIP link). Args: endpoint: Endpoint name from config (protocol 'ethernetip'/'eip'); omit for default. plctype: Driver selector override — 'logix' (default), 'slc' (PLC-5/SLC-500/ MicroLogix, PCCC), or 'micro800'. Omit to use the endpoint's configured plctype. Returns dict: {endpoint, host, slot, plctype, controller, info_error}. For logix/micro800 controller carries {vendor, product_type, revision, serial, product_name, name, ...}; for slc it carries {processor_type}. Example: eip_controller_info(endpoint="slc05", plct…

  • eip_list_tags

    [READ][risk=low] Discover the controller's tags (Logix) or PCCC data files (SLC). Logix/Micro800: enumerate the controller's symbol table without prior knowledge (program-scoped tags appear as 'Program:<prog>.<tag>'). SLC/PCCC has no symbol table, so the data-file directory (N7/B3/F8/... with element counts) is returned instead. Args: endpoint: Endpoint name from config. plctype: Driver selector override — 'logix' (default), 'slc', or 'micro800'. Returns dict: logix → {endpoint, plctype, tag_count, tags:[{name, data_type, tag_type, structure, dimensions}]}; slc → {endpoint, plct…

  • eip_read_many

    [READ][risk=low] Batch-read many tags/addresses in one request. Args: tags: Logix tag names (["Speed", "Temp", "Array[0]"]) OR SLC/PCCC data-table addresses (["N7:0", "F8:0", "B3:0/0"]). endpoint: Endpoint name from config. plctype: Driver selector override — 'logix' (default), 'slc' (PCCC), or 'micro800'. Returns dict: {endpoint, plctype, count, items:[{tag, value, type, error, good}]}. Example: eip_read_many(tags=["Speed","Temp"], endpoint="cell5"); eip_read_many(tags=["N7:0","F8:0"], endpoint="slc05", plctype="slc").

  • eip_read_tag

    [READ][risk=low] Read one tag/address with its type. Args: tag: Logix tag ('Conveyor.Speed', 'Array[3]', 'Program:Main.X') OR an SLC/PCCC data-table address ('N7:0' int, 'B3:0/0' bit, 'F8:0' float, 'T4:0.ACC', 'N7:0{10}' slice). endpoint: Endpoint name from config. plctype: Driver selector override — 'logix' (default), 'slc' (PCCC), or 'micro800'. Returns dict: {endpoint, plctype, tag, value, type, error, good}. Example: eip_read_tag(tag="Conveyor.Speed", endpoint="cell5"); eip_read_tag(tag="N7:0", endpoint="slc05", plctype="slc").

  • eip_write_tag

    [WRITE][risk=HIGH][MOC] Write ONE value to a tag/data-table address (off by default). OT-DANGEROUS. Defaults to dry_run=True (nothing written). Captures the BEFORE value (read-back) and records an undo descriptor so the change is reversible. Set dry_run=False AND record an approver (OPCUA_AUDIT_APPROVED_BY) to apply. 未经授权勿对生产控制系统写入. Args: tag: Logix tag name OR SLC/PCCC data-table address ('N7:0', 'F8:0', 'B3:0/0'). value: Value to write (pycomm3 coerces to the tag's CIP/PCCC type). endpoint: Endpoint name from config. plctype: Driver selector override — 'logix' (default), 's…

  • ethercat_master_state

    [READ][risk=low] Open the master on the configured NIC; report bus state. Needs Linux + root/CAP_NET_RAW + a dedicated NIC + real slaves (pysoem extra). Degrades to a teaching error dict if pysoem/permission/NIC/bus is missing. Args: endpoint: Endpoint name from config (protocol 'ethercat'); omit for default. Returns dict: {endpoint, nic, master_state (INIT/PREOP/SAFEOP/OP/...), expected_working_counter, slaves_found, slaves_expected, slave_count_ok}. Example: ethercat_master_state(endpoint="bus1").

  • ethercat_read_pdo

    [READ][risk=low] One cyclic snapshot of a slave's input process-data image. Does a single send/receive cycle (never loops) and returns the input image. Args: slave: Zero-based slave index. endpoint: Endpoint name from config. Returns dict: {endpoint, slave, working_counter, input_byte_length, input_hex, output_byte_length}. Example: ethercat_read_pdo(slave=0, endpoint="bus1").

  • ethercat_read_sdo

    [READ][risk=low] CoE SDO upload: read one object-dictionary entry (acyclic). Args: slave: Zero-based slave index. index: CoE object index (decimal, e.g. 0x1018 → 4120). subindex: Sub-index (default 0). size: Expected byte size (0 = let SOEM size it). endpoint: Endpoint name from config. Returns dict: {endpoint, slave, index, subindex, byte_length, hex, as_uint}. Example: ethercat_read_sdo(slave=0, index=0x1018, subindex=1, endpoint="bus1").

  • ethercat_set_state

    [WRITE][risk=HIGH][MOC] Request an AL-state transition (off by default). OT-DANGEROUS: moving to/from OP can START or STOP machine motion. Defaults to dry_run=True. ``slave`` < 0 applies to the master (all slaves). Captures the CURRENT state for undo. Set dry_run=False AND record an approver to apply. 未经授权勿对生产控制系统写入. Args: state: Target AL-state: INIT | PREOP | SAFEOP | OP (or a numeric code). slave: Zero-based slave index, or -1 (default) for the whole master. endpoint: Endpoint name from config. dry_run: When True (default) returns a preview without changing state. Returns…

  • ethercat_slave_info

    [READ][risk=low] Detail one slave: identity, SM/FMMU config, OD summary. Args: slave: Zero-based slave index (from ethercat_slaves). endpoint: Endpoint name from config. Returns dict: {endpoint, index, name, vendor_id, product_code, revision, config_addr, state, input_bytes, output_bytes, sync_managers[], fmmus[], object_dictionary:[{index, name, entry_count}]}. Example: ethercat_slave_info(slave=0, endpoint="bus1").

  • ethercat_slaves

    [READ][risk=low] Bus scan: enumerate every slave on the segment. Args: endpoint: Endpoint name from config (protocol 'ethercat'). Returns dict: {endpoint, slave_count, slaves:[{index, name, vendor_id, product_code, revision, config_addr, state}]}. Example: ethercat_slaves(endpoint="bus1").

  • ethercat_write_sdo

    [WRITE][risk=HIGH][MOC] CoE SDO download: write one OD entry (off by default). OT-DANGEROUS. Defaults to dry_run=True (nothing written). ``value`` is a hex string of the raw little-endian bytes (e.g. 'e803' = 1000 as uint16). Captures the BEFORE value (SDO read-back) and records an undo descriptor. Set dry_run=False AND record an approver to apply. 未经授权勿对生产控制系统写入. Args: slave: Zero-based slave index. index: CoE object index (decimal, e.g. 0x607A → 24698). value: Hex string of raw little-endian bytes to write. subindex: Sub-index (default 0). endpoint: Endpoint name from c…

  • export_data

    [READ][risk=low] Export collected samples from the LOCAL SQLite sink to a file. Source is ~/.iaiops/data.db — the local queryable store written by historian_push(sink="sqlite") — NOT a live device read. Writes csv (Excel), sqlite (SQL browser / Power BI) or parquet (pandas/Spark; needs pip install 'iaiops[export]'), and returns the file path + row count with a bounded inline preview (first 200 rows max) so the response never floods. Args: fmt: 'csv' | 'sqlite' | 'parquet'. since/until: Optional ISO-8601 time bounds (inclusive). endpoint: Only samples from this endpoint label. …

  • fins_cpu_info

    [READ][risk=low] Omron CPU model/version via FINS 0501 (proves the link). Args: endpoint: Endpoint name from config (protocol must be 'fins'); omit for default. Returns dict: {endpoint, model, version}. Example: fins_cpu_info(endpoint="line2").

  • fins_cpu_status

    [READ][risk=low] Omron controller status via FINS 0601 (run/stop, mode, errors). Args: endpoint: Endpoint name from config (protocol must be 'fins'). Returns dict: {endpoint, status, mode, fatal_error_data, non_fatal_error_data}. Example: fins_cpu_status(endpoint="line2").

  • fins_read_bits

    [READ][risk=low] Read bits from an Omron memory area (FINS 0101, bit codes). Args: area: Bit-capable area: "CIO", "W", "H", "A", or "DM". address: Word address the first bit lives in, e.g. 0 for CIO 0.00. bit: Bit number within the word (0..15). endpoint: Endpoint name from config. count: Number of consecutive bits (1..256). Returns dict: {endpoint, area, address, bit, count, bits:[bool,...]}. Example: fins_read_bits(area="CIO", address=0, bit=0, count=16).

  • fins_read_many

    [READ][risk=low] Batched word reads over one FINS session (bounded). Args: endpoint: Endpoint name from config. items: Read specs, each {"area": "DM", "address": 100, "count": 2} (max 20 items, count capped at 500 each). Returns dict: {endpoint, reads:[{area, address, count, words:[int,...]}]}. Example: fins_read_many(items=[{"area":"DM","address":100,"count":2}, {"area":"CIO","address":0,"count":1}]).

  • fins_read_words

    [READ][risk=low] Read 16-bit words from an Omron memory area (FINS 0101). Args: area: Memory area: "DM", "CIO", "W", "H", "A", or "EM" (current bank). address: Word address to start at, e.g. 100 for DM100. endpoint: Endpoint name from config. count: Number of consecutive words (1..500, capped server-side). Returns dict: {endpoint, area, address, count, words:[int,...]} (unsigned 16-bit). Example: fins_read_words(area="DM", address=100, count=8).

  • fins_write_words

    [WRITE][risk=HIGH][MOC] Write 16-bit words to an Omron area (off by default). OT-DANGEROUS. Defaults to dry_run=True. Captures the BEFORE values (read-back of the same range) and records an undo descriptor. Set dry_run=False AND record an approver (OPCUA_AUDIT_APPROVED_BY) to apply. 未经授权勿对生产控制系统写入. Args: area: Memory area to write: "DM", "CIO", "W", "H", "A", or "EM". address: Word address to start at, e.g. 100 for DM100. values: List of 16-bit word values to write (length 1..500). endpoint: Endpoint name from config. dry_run: When True (default) returns a preview without…

  • fleet_incidents

    [READ][risk=low] Roll up active RCA incidents across sites → fleet-wide top causes. Aggregates the incidents each site reports into a fleet picture: how many incidents, which sites are affected, and the most common root causes across the whole fleet. Read-only; no device I/O. Args: sites: Per-site reports carrying incidents: [{site, incidents:[{cause|primary_cause, confidence?}]}]. Returns dict: {total_incidents, sites_with_incidents, affected_sites[], top_causes[]}. Example: fleet_incidents(sites=[{"site":"plant-sh","incidents":[{"cause":"network"}]}]).

  • fleet_status

    [READ][risk=low] Roll up per-site status reports into one fleet health view. The tier above data_quality_fleet_rollup (per-endpoint within one site): this aggregates across many edge SITES for central management. A site is 'offline' if its last_seen is older than stale_after_s; fleet_status is the worst site status present. Read-only, pure; no device I/O. Args: sites: Per-site reports, each [{site, location?, profile?, status?, score?, issues?, last_seen?}]; status ∈ ok|degraded|critical|offline (else derived from score); score 0..1. stale_after_s: A site with no repo…

  • hart_burst_listen

    [READ][risk=low] Passively LISTEN for unsolicited HART burst-publish messages. Unlike hart_burst_sample (which actively re-polls), this receives whatever the device/gateway PUBLISHES on its own burst schedule — no polling — for up to duration_s seconds or max_messages, decoding each HART-IP publish (message type 2) with the same command-3 parser. Needs a gateway that forwards unsolicited publishes on the session socket (待核实 per gateway); a device not in burst mode yields nothing — hart_burst_sample is the active fallback. Args: endpoint: Endpoint name from config (protocol 'hart'); omit …

  • hart_burst_sample

    [READ][risk=low] Sample the periodically-published (burst) HART variables. HART burst mode has the field device publish its dynamic variables periodically. A true unsolicited HART-IP burst subscription is 待核实 (no live gateway); this actively samples the same published set (command 3 — dynamic variables + loop current) ``samples`` times over one session, so an agent can see the published variables and spot a stuck/frozen reading. Read-only; no burst config is written. Args: endpoint: Endpoint name from config (protocol 'hart'); omit for default. samples: Number of samples to collect (…

  • hart_device_identity

    [READ][risk=low] HART universal device identity (command 0) via HART-IP. Args: endpoint: Endpoint name from config (protocol 'hart'); omit for default. Returns dict: {endpoint, host, command, manufacturer_id, device_type, device_id, hart_revision}.

  • hart_dynamic_variables

    [READ][risk=low] HART dynamic variables + loop current (command 3) via HART-IP. Args: endpoint: Endpoint name from config (protocol 'hart'); omit for default. Returns dict: {endpoint, host, command, loop_current_mA, variable_count, variables:[{name, value, unit_code}]}.

  • hart_primary_variable

    [READ][risk=low] HART primary variable (command 1): value + unit code. Args: endpoint: Endpoint name from config (protocol 'hart'); omit for default. Returns dict: {endpoint, host, command, primary_variable, unit_code, device_status}.

  • health_summary

    [DEPRECATED → opcua_health_summary][READ][risk=low] Classify OPC-UA tags. Classifies tag node-ids against warn/alarm thresholds. Returns ok/warn/alarm/unknown counts plus the offending tags. Thresholds come from config tags, or per-ref overrides in ``thresholds``. Args: endpoint: Endpoint name from config. node_ids: Tag node ids to evaluate; omit to use configured tags. thresholds: Optional {ref: {warn_high, alarm_high, warn_low, alarm_low}}.

  • heartbeat_health

    [READ][risk=low] Is a heartbeat/watchdog tag still alive? (liveness check). A heartbeat must keep CHANGING; a flatlined one means the upstream is dead even when comms/quality look fine. With timestamped samples + max_interval_s, also flags the longest stall. Args: series: Heartbeat samples — scalars or {value, timestamp?} (a counter/toggle). max_interval_s: Max allowed gap between changes; exceeding it = not alive. Returns dict: {alive (bool), samples, distinct_transitions, spread, longest_stall_s, reason}. Example: heartbeat_health(series=[1,2,3,4,5], max_interval_s=10).

  • heat_exchanger_fouling

    [READ][risk=low] Detect heat-exchanger fouling from stream-temperature trend. Is the exchanger fouling? Computes hot-side temperature effectiveness ε = (hot_in − hot_out)/(hot_in − cold_in) per reading, and compares the window's first half to its second half. Verdict is 'fouling' when the mean effectiveness is below min_effectiveness or it declined more than decline_pct — the signature that precedes a forced clean. Pure analysis over readings you pass in (OPC-UA/ Modbus/HART temperature points); read-only, cited by the effectiveness numbers. Args: readings: [{hot_in, hot_out, cold_in, co…

  • historian_coverage

    [READ][risk=low] Per-tag history coverage — what history do we actually have. Answers the question every RCA starts with: which tags have stored history, how many rows, and over what time span — per tag {rows, first_ts, last_ts} from the same store historian_push writes. Read-only, bounded (tag list is capped with a truncation flag); no device I/O. Args: reader: 'sqlite' | 'tdengine' | 'iotdb'. Omit to use the per-site 'historian:' block in ~/.iaiops/config.yaml, else the local sqlite store. TSDB readers need their extra: pip install iaiops[tdengine|iotdb]. limit: Max…

  • historian_health

    [READ][risk=low] Bad-tag / flatline / gap detection over a provided series. Pure analysis over an injected sample series — no live historian needed. Args: series: Samples — scalars or {value, timestamp (ISO-8601), quality|good}. gap_threshold_s: Time gap (seconds) between consecutive samples that counts as a data gap (default 60). flatline_eps: Spread at/below which the series counts as flatline. Returns dict: {samples, numeric_samples, bad_quality_count, flatline (bool), gap_count, gaps:[{after, gap_seconds}], stdev, verdict ('ok'|'degraded'|'gappy'|'flatline'|'…

  • historian_push

    [WRITE][risk=low][→historian] Push collected telemetry to a national TSDB. Writes already-collected points to a domestic historian (信创) — TDengine or IoTDB — instead of binding InfluxDB. Data egress to the operator's OWN database, NOT a control-system write. Non-numeric points are skipped (numeric value column). Args: points: Collected points — {ref|metric, value|present_value, timestamp?, ...} (e.g. the output of interrogate / integrity_poll / read_points / monitor). sink: 'tdengine' or 'iotdb'. host/port/user/password: TSDB connection params (sensible defaults per sink …

  • historian_query

    [READ][risk=low] Query a tag's historical samples from a historian. Reads history back OUT of the store the sinks write — the local SQLite store (~/.iaiops/data.db), TDengine, or IoTDB — so the RCA copilot / an agent can see real pre-incident windows instead of only short live samples. Read-only over the operator's OWN historian; no device I/O. Bounded: rows are capped and a truncation flag is set when more history exists. Args: tag: Tag/metric name as stored by historian_push (e.g. 'line1.temp'). since/until: Optional ISO-8601 time bounds (inclusive). endpoint: Only samples from…

  • ignition_alarm_status

    [READ][risk=low] Active/acknowledged alarm list (normalized). Args: base_url: Gateway HTTP base URL. flavor: Gateway API deployment dialect — 'webdev' or 'gateway'. secret_name: Secret-store key holding the API token (omit if none). verify_tls: Verify the Gateway's TLS certificate (default True). Passing False is refused unless the operator set IAIOPS_ALLOW_INSECURE_TLS=1. Returns dict: {flavor, base_url, alarm_count, alarms:[{name, source, priority, state, label, timestamp}]}. Example: ignition_alarm_status(base_url="https://gw:8043", flavor="webdev").

  • ignition_gateway_status

    [READ][risk=low] Gateway/module health + reachability (the Gateway doctor step). Talks to the vendor SCADA/MES platform's Gateway HTTP web API (not OPC-UA — that stays on the opcua connector). The API token is resolved from the encrypted secret store by key name, never passed inline. Token-egress guard: with a secret set, base_url must point at an internal host (private IP / single-label / .local-style name) or a host the operator allowlisted via IAIOPS_TOKEN_EGRESS_HOSTS — public hosts are refused before any request (prevents stored-token exfiltration). Args: base_url: Gateway HTTP base…

  • ignition_tag_browse

    [READ][risk=low] Browse the tag tree under a provider/path. Args: base_url: Gateway HTTP base URL. provider: Tag provider name (e.g. 'default'). path: Folder path under the provider to browse (blank = root). flavor: Gateway API deployment dialect — 'webdev' or 'gateway'. secret_name: Secret-store key holding the API token (omit if none). verify_tls: Verify the Gateway's TLS certificate (default True). Passing False is refused unless the operator set IAIOPS_ALLOW_INSECURE_TLS=1. Returns dict: {flavor, base_url, provider, path, node_count, nodes:[{name, path…

  • ignition_tag_history

    [READ][risk=low] Historian query for one tag over a time window (aggregated). Args: base_url: Gateway HTTP base URL. provider: Tag provider name (e.g. 'default'). tag_path: Tag path whose history to query. start: Window start (ISO-8601 or the gateway's accepted time string). end: Window end (ISO-8601 or the gateway's accepted time string). count: Max samples to return (1..5000, capped server-side). flavor: Gateway API deployment dialect — 'webdev' or 'gateway'. secret_name: Secret-store key holding the API token (omit if none). verify_tls: Verify the Gatewa…

  • ignition_tag_read

    [READ][risk=low] Current value(s)/quality/timestamp for tag path(s). Args: base_url: Gateway HTTP base URL. provider: Tag provider name (e.g. 'default'). tag_paths: Tag paths to read (from ignition_tag_browse). flavor: Gateway API deployment dialect — 'webdev' or 'gateway'. secret_name: Secret-store key holding the API token (omit if none). verify_tls: Verify the Gateway's TLS certificate (default True). Passing False is refused unless the operator set IAIOPS_ALLOW_INSECURE_TLS=1. Returns dict: {flavor, base_url, provider, tag_count, tags:[{path, value, qu…

  • investigation_list

    [READ][risk=low] List saved investigations, newest first.

  • investigation_open

    [READ][risk=low] Open an investigation over one past window and walk what can be walked. Contacts no device — the window is already past, and its evidence is whatever was collected at the time. Each of the eight steps records its own outcome: `done` (it ran, here is what it found), `refused` (it could not run HERE — no samples, no alarm source; a site fact) or `not_possible` (this product cannot do it at all). The investigation is persisted, so it can be re-read and advanced later.

  • investigation_readiness

    [READ][risk=low] How far into an investigation this site could get, and what each gap needs. `readiness` answers "which scenarios can this site run"; this answers the next question down — if something stopped tomorrow, how many of the eight evidence steps could actually be walked, and for each one that could not, what is missing. Contacts nothing: no device, no network, no historian. It is derived from the config and the local store, which is what makes it usable on a site nobody has been authorised to probe yet. Each gap says whether it is *unmet* (you have not supplied it — the fix names …

  • investigation_show

    [READ][risk=low] Re-read a saved investigation — the state it was left in.

  • iolink_device_info

    [READ][risk=low] Identity of the IO-Link device on one master port. Args: port: Master port number (1..32). endpoint: Endpoint name from config. Returns dict: {endpoint, port, device:{vendorid, deviceid, productname, serial, status}, unavailable?:{field: error}}. Example: iolink_device_info(port=1, endpoint="master1").

  • iolink_master_info

    [READ][risk=low] IO-Link master identity (productcode/serial/hw/sw revision). Reads the master's /deviceinfo tree over its JSON interface (ifm IoT-Core envelope or plain REST, per the endpoint's flavor). Args: endpoint: Endpoint name from config (protocol must be 'iolink'). Returns dict: {endpoint, flavor, master:{productcode, serialnumber, hwrevision, swrevision}, unavailable?:{field: error}}. Example: iolink_master_info(endpoint="master1").

  • iolink_ports

    [READ][risk=low] BOUNDED port sweep: mode/status + connected device identity. Call this first to see which ports carry an IO-Link device before reading process data. Args: endpoint: Endpoint name from config. count: Ports to sweep (1..32, capped server-side). Returns dict: {endpoint, ports_checked, ports_present, devices_connected, ports:[{port, present, mode, device_connected, device_status, vendorid, deviceid, productname}]}. Example: iolink_ports(endpoint="master1", count=8).

  • iolink_read_isdu

    [READ][risk=low] ISDU acyclic parameter read (iolreadacyclic) — bounded. Args: port: Master port number (1..32). index: ISDU parameter index (0..65535). subindex: ISDU subindex (0..255, default 0). endpoint: Endpoint name from config. Returns dict: {endpoint, port, index, subindex, value} (value typically a hex string of the parameter octets; master-dependent). Example: iolink_read_isdu(port=1, index=16, endpoint="master1").

  • iolink_read_pdin

    [READ][risk=low] Process-data-in of one port: raw hex + decoded byte array. The byte layout is device-specific — decode per the device's IODD. Args: port: Master port number (1..32). endpoint: Endpoint name from config. Returns dict: {endpoint, port, pdin_hex, bytes:[int], byte_count, note}. Example: iolink_read_pdin(port=1, endpoint="master1").

  • iolink_scan

    [READ][risk=low] One-shot BOUNDED snapshot: master identity + all ports. Args: endpoint: Endpoint name from config. count: Ports to sweep (1..32, capped server-side). Returns dict: {endpoint, flavor, master:{...}, ports_checked, ports_present, devices_connected, ports:[{port, present, mode, device_connected, ...}]}. Example: iolink_scan(endpoint="master1").

  • isolation_room_check

    [READ][risk=low] Isolation-room pressurization compliance (ASHRAE 170 / CDC). The healthcare-facility safety check generic BMS lacks: airborne-infection isolation (AII) rooms must stay NEGATIVE to the corridor, protective- environment (PE) rooms POSITIVE, at a minimum ~2.5 Pa differential. Grades each room from its differential-pressure reading — 'reversed' (wrong polarity, a reportable safety event), 'breach' (right polarity but too weak), 'low_margin', or 'compliant' — worst-first, citing the number behind every flag. Pure analysis over readings you pass in (differential-pressure AI points …

  • learn_cause_weights

    [READ][risk=low] Learn a per-site RCA {cause: weight} profile from history. Derives a per-site cause-weight profile from a corpus of CONFIRMED past incidents so downtime_root_cause adapts to what THIS site's evidence actually predicts. Pure + explainable: each weight is the smoothed signal→cause precision relative to chance (>1 = evidence for that cause is reliable here, <1 = often misleading) — no black box. Anti-overfit: Laplace smoothing + a per-cause min-sample guard, and a fall-back to the shipped defaults when the corpus is too thin. Feed the returned 'cause_weights' to downtime_root_ca…

  • line_bottleneck

    [READ][risk=low] Find a material-handling / production line's throughput constraint. Theory-of-Constraints over per-station data: a line runs no faster than its slowest station, so the bottleneck is the station with the lowest throughput (longest cycle time). Starvation/blocking corroborate — the constraint is rarely starved or blocked, while upstream stations block and downstream stations starve. Ranks the line, names the constraint and the line rate it sets, flags co-constraints running close behind, and tags each station starved / blocked — every call citing the number. Pure analysis over …

  • line_relation_declare

    [READ][risk=low] Record that one asset feeds another — the second RCA axis. `[READ]` follows this repo's convention, where the tag is about PLANT state: it touches no device, exactly like `baseline_record_change` and `adopt_alias_map`, which are the same shape. It does write — a declaration about the line, into the site knowledge base. With time alone, an upstream stoppage produces a string of equally-confident downstream false causes, because on a line downstream co-occurrence is guaranteed whatever the cause. That guarantee is exactly why this is a declaration and not something inferred (D…

  • line_relations_list

    [READ][risk=low] The declared line order for a site, and what each asset feeds.

  • mc_cclink_link_read

    [READ][risk=low] Read a CC-Link refresh image (RX/RY/RWr/RWw) via the master PLC. Zero network membership: reads the PLC-side refresh image of the CC-Link / CC-Link IE link devices over the existing MC/SLMP connection (docs/CCLINK.md). Args: template: Template name (see mc_cclink_templates), e.g. "cclink_ie_field_default". endpoint: Endpoint name from config (protocol must be 'mc'); the CC-Link MASTER PLC. overrides: Remap area head devices per the project's refresh parameters, e.g. {"rx": "X1200", "rwr": "W200:8"} ("HEAD" or "HEAD:COUNT"). Returns dict: {endpoint, templ…

  • mc_cclink_network_health

    [READ][risk=low] Per-station CC-Link data-link health from the master's SB/SW registers. Decodes the master's link special registers (classic CC-Link: SW0080–; CC-Link IE Field: SB0049 own-station error + SW00B0– per-station + SW00A0– baton pass) into one row per station — network RCA evidence with zero CC-Link hardware (docs/CCLINK.md). Args: endpoint: Endpoint name from config (protocol must be 'mc'); the CC-Link MASTER PLC. network: "cclink" (classic) or "cclink_ie_field". stations: Station numbers to decode, 1..N (classic max 64, IE Field max 120). Returns dict: {endpoint, n…

  • mc_cclink_templates

    [READ][risk=low] List CC-Link refresh-image templates (master-PLC route, no device I/O). CC-Link/CC-Link IE data is read THROUGH the Mitsubishi master PLC (SLMP/MC) — see docs/CCLINK.md. Each template is a documented default RX/RY/RWr/RWw ↔ PLC-device layout; the real refresh assignment is per-project (待核实 per site). Returns dict: {templates:[{name, network, description, areas, caveat}]}. Example: mc_cclink_templates().

  • mc_cpu_status

    [READ][risk=low] MELSEC CPU type/code (proves the MC link is alive). Args: endpoint: Endpoint name from config (protocol must be 'mc'); omit for default. Returns dict: {endpoint, plctype, cpu_type, cpu_code}. Example: mc_cpu_status(endpoint="cell3").

  • mc_read_bits

    [READ][risk=low] Batch-read bit devices from a head device. Args: headdevice: MELSEC bit device, e.g. "M0", "X10", "Y20", "B0". endpoint: Endpoint name from config. count: Number of consecutive bits (1..256). Returns dict: {endpoint, headdevice, count, bits:[bool,...]}. Example: mc_read_bits(headdevice="M0", count=16).

  • mc_read_many

    [READ][risk=low] Random-read scattered word + dword devices in one request. Args: endpoint: Endpoint name from config. word_devices: Word device names, e.g. ["D100", "D200", "M0"]. dword_devices: Double-word device names, e.g. ["D300", "D400"]. Returns dict: {endpoint, words:[{device, value}], dwords:[{device, value}]}. Example: mc_read_many(word_devices=["D100","D101"], dword_devices=["D200"]).

  • mc_read_words

    [READ][risk=low] Batch-read 16-bit word devices from a head device. Args: headdevice: MELSEC word device, e.g. "D100", "W10", "R0". endpoint: Endpoint name from config. count: Number of consecutive words (1..256, capped server-side). Returns dict: {endpoint, headdevice, count, words:[int,...]} (signed 16-bit). Example: mc_read_words(headdevice="D100", count=8).

  • mc_write_words

    [WRITE][risk=HIGH][MOC] Write 16-bit words from a head device (off by default). OT-DANGEROUS. Defaults to dry_run=True. Captures the BEFORE values (read-back of the same range) and records an undo descriptor. Set dry_run=False AND record an approver (OPCUA_AUDIT_APPROVED_BY) to apply. 未经授权勿对生产控制系统写入. Args: headdevice: MELSEC word device to start at, e.g. "D100". values: List of 16-bit word values to write (length 1..256). endpoint: Endpoint name from config. dry_run: When True (default) returns a preview without writing. Returns dict: dry-run → {headdevice, dry_run:true, bef…

  • mechanism_library_check

    [READ][risk=low] What a mounted fault-mechanism library says about one candidate cause. Three answers, and the difference between the first two is the whole point: * ``nothing_known`` — the library has never heard of this cause. **Not** "no objection": a knowledge base that knows nothing about something has not cleared it. * ``known``, not excluded — mechanisms for it apply here, with what would confirm each. * ``known``, excluded — every mechanism for it is inapplicable to this equipment, so the candidate can be ruled out. That is the strong move a ranker cannot make. It never co…

  • mechanism_library_list

    [READ][risk=low] The fault mechanisms mounted for a site, and where each came from.

  • medical_gas_check

    [READ][risk=low] Medical-gas / vacuum source pressure compliance (NFPA 99 / HTM 02-01). The other healthcare-facility safety check: grades each medical-gas source's pressure against its NFPA 99 band — positive-pressure gases (oxygen / medical air / N2O / nitrogen / CO2) must sit inside ~345–380 kPa; medical vacuum / WAGD must be at least as deep as the vacuum threshold. Each source → 'normal' / 'low_pressure' / 'high_pressure' / 'insufficient_vacuum' / 'critical', worst-first, citing the number. Pure analysis over readings you pass in (from BACnet AI points or the gas alarm panel); read-only,…

  • meter_hh_check

    [READ][risk=low] What a supplier half-hourly electricity CSV contains, before analysis. Detects the layout (wide: date + 46–50 half-hour columns; long: timestamp + kWh), lists meters (MPAN) with their first/last half hour in UK local time, and counts what was rejected: blank / non-numeric cells (kept as MISSING, never zero), negative values, non-UK dates, clock-change mismatches, conflicting duplicates. Also returns every assumption the parser made (unit, timestamp convention, unknown read type). Pure analysis of the text you pass; no device contacted. Args: csv_text: The CSV file conten…

  • meter_load_profile

    [READ][risk=low] Where and when a site uses electricity, from supplier half-hourly data. Per meter: coverage (missing half hours are counted, never filled or scaled up), measured kWh, estimated-read share (or 'unknown' when the file has no flag), peak kW and when, overnight base load (median 00:00–05:00), out-of-hours kWh and share against the DECLARED operating hours, out-of-hours use above base load (an indication of opportunity, not a guaranteed saving), complete-day weekday vs weekend averages, load factor, plain-English findings and warnings. With a ``tariff``, cost by time band, standin…

  • modbus_apply_template

    [READ][risk=low] Read a register block and decode it into named tags via a template. Args: template: Template name (see modbus_list_templates). endpoint: Endpoint name from config. address: Absolute address of the first register read (aligns to offsets). count: Registers to read; omit to use the template's span.

  • modbus_detect_byte_order

    [READ][risk=low] Auto-detect the word/byte order of a raw Modbus register block. Pure decode logic (no device): decodes the raw registers under every candidate order for the numeric type and scores them against a known/expected value and/or a plausible range. Solves the "right registers, wrong endianness" pain. Args: registers: Raw 16-bit register values (e.g. from modbus_read_holding). value_type: uint16|int16|uint32|int32|float32. hint: A known/expected sample value to match against. value_min: Lower bound of a plausible value band. value_max: Upper bound of a plausible…

  • modbus_health_summary

    [READ][risk=low] Classify Modbus registers against warn/alarm thresholds. Mirrors the OPC-UA health_summary classifier. Returns ok/warn/alarm/unknown counts plus offenders; ``overall`` is ``unknown`` when nothing is in warn/alarm and any point could not be classified (``ok`` means every point was observed in band), and ``coverage`` (complete|partial|none) says how many points were judged at all — an alarm with ``coverage: partial`` is not the only problem. Configured tags may be typed points (``ir:0:float32:CDAB``) or profile channels (``ch:<name>``, decoded through the endpoint's sensor_prof…

  • modbus_list_templates

    [READ][risk=low] List built-in vendor register-map templates (name / type / tags).

  • modbus_read_coils

    [READ][risk=low] Read coils (FC01) — digital outputs, read-only here. Args: address: Starting coil address. endpoint: Endpoint name from config. count: Number of coils.

  • modbus_read_discrete

    [READ][risk=low] Read discrete inputs (FC02) — read-only digital inputs. Args: address: Starting discrete-input address. endpoint: Endpoint name from config. count: Number of inputs.

  • modbus_read_holding

    [READ][risk=low] Read holding registers (FC03) with a decode hint. Args: address: Starting register address. endpoint: Endpoint name from config. count: Number of registers (capped server-side). decode: raw|uint16|int16|uint32|int32|float32.

  • modbus_read_input

    [READ][risk=low] Read input registers (FC04) with a decode hint. Args: address: Starting register address. endpoint: Endpoint name from config. count: Number of registers (capped server-side). decode: raw|uint16|int16|uint32|int32|float32.

  • monitor_changes

    [READ][risk=low] Capture only the value CHANGES of a point over a bounded window. Polls ``ref`` and returns only the changes (with timestamps), not every sample — the OT deadband-report pattern. Works across OPC-UA / Modbus / S7 / Mitsubishi MC / EtherNet/IP. Hard-capped by duration_s and max_changes (never an infinite loop). Args: ref: Point to watch — OPC-UA node id, Modbus address, S7 address string, MELSEC device, or Logix tag (per the endpoint's protocol). endpoint: Endpoint name from config. duration_s: Wall-clock window in seconds (1..120, capped server-side). …

  • mqtt_publish

    [WRITE][risk=HIGH][MOC] Publish/command to an MQTT topic (off by default). OT-DANGEROUS. A command (e.g. Sparkplug NCMD/DCMD) can change a live control system. Defaults to dry_run=True. Set dry_run=False AND record an approver (OPCUA_AUDIT_APPROVED_BY) to send. 未经授权勿对生产控制系统下发指令. Reversibility depends on retain: a transient (retain=False) command has NO inverse — delivered is delivered. A RETAINED publish overwrites durable broker state, so the prior retained payload is captured first (returned as `before`) and an undo descriptor recorded, as the protocol write tools do. Args: topic: MQT…

  • mqtt_read_topic

    [READ][risk=low] Plain MQTT: collect a BOUNDED set of messages from a topic. Subscribes, gathers up to ``count`` messages or until ``timeout_s``, then disconnects — never an open-ended loop. Payloads are decoded as JSON/text; binary (e.g. Sparkplug protobuf) is reported with a hex preview + hint. Args: endpoint: Endpoint name from config (protocol must be 'mqtt'). topic: Topic filter (default: the endpoint's configured topic or '#'). count: Max messages (1..500, capped server-side). timeout_s: Max seconds to wait (1..60, capped server-side). Returns dict: {endpoint, topic, m…

  • mtconnect_assets

    [READ][risk=low] Assets the agent knows (cutting tools, fixtures, programs). Args: endpoint: Endpoint name from config. Returns dict: {endpoint, asset_count, assets:[{asset_type, asset_id, timestamp}]}. Example: mtconnect_assets(endpoint="vmc1").

  • mtconnect_current

    [READ][risk=low] Latest value of every data item (a snapshot of the machine now). Args: endpoint: Endpoint name from config. Returns dict: {endpoint, observation_count, next_sequence, observations:[{data_item_id, type, name, timestamp, sequence, value}]}. Pass next_sequence as from_sequence to mtconnect_sample to stream from 'now'. Example: mtconnect_current(endpoint="vmc1").

  • mtconnect_oee_snapshot

    [READ][risk=low] Availability / Execution / mode / program (OEE inputs). Surfaces the live data items an availability/performance calc needs. Does NOT compute a single OEE % (needs planned-time + ideal-cycle context MTConnect doesn't expose). Args: endpoint: Endpoint name from config. Returns dict: {endpoint, availability, execution, controller_mode, program, available (bool), running (bool), verdict ('running'|'available_idle'|'down')}. Example: mtconnect_oee_snapshot(endpoint="vmc1").

  • mtconnect_probe

    [READ][risk=low] The device model: devices → components → data items. The MTConnect 'schema' — what the machine can report. Call this first to discover dataItem ids/types before reading values. Args: endpoint: Endpoint name from config (protocol must be 'mtconnect'). Returns dict: {endpoint, device_count, devices:[{name, uuid, component_count, components:[{component, id, name, data_items:[{id, type, category, name, units}]}]}]}. Example: mtconnect_probe(endpoint="vmc1").

  • mtconnect_sample

    [READ][risk=low] Recent observations — a bounded snapshot OR a bounded incremental long-poll stream. Both modes are read-only and can NEVER run unbounded. Modes: - snapshot (default): one /sample page of up to `count` observations. Pass `from_sequence` for a single incremental page starting at that sequence. - stream: set `max_samples` and/or `duration_s` to poll the agent repeatedly, advancing by the header's nextSequence each round, until a bound is hit. Feed the returned `next_sequence` back as `from_sequence` to resume exactly where you stopped. Args: endpoint: En…

  • oee_compute

    [READ][risk=low] OEE = Availability × Performance × Quality (+ loss/energy depth). Args: planned_time_s: Planned production time (seconds). run_time_s: Actual running time (seconds) — planned minus downtime. ideal_cycle_time_s: Ideal/nameplate cycle time per part (seconds). total_count: Total parts produced. good_count: Good (non-reject) parts produced. breakdown_time_s: Optional — unplanned-stop seconds (splits availability loss). setup_time_s: Optional — changeover/setup seconds (splits availability loss). minor_stop_time_s: Optional — minor-stop seconds (spl…

  • oee_multidim

    [READ][risk=low] Aggregate OEE (+ optional energy) across dimensions. Args: records: Labelled records — {<dimension labels>, planned_time_s, run_time_s, ideal_cycle_time_s, total_count, good_count} plus optional actual_kwh / baseline_kwh to enable the energy rollup. dimensions: Dimension keys to group by (default ['machine','part','shift']); use ['shift'] for the classic by-shift energy comparison. emission_factor_kg_per_kwh: Optional carbon factor (kg CO2e/kWh); default is a flagged placeholder — pass the grid's published value. energy_toleranc…

  • onboarding_config_draft

    [READ][risk=low] The config.yaml endpoints a stored scan can justify. Closes the gap where a site scanned forty devices and then retyped all forty by hand. Reads a stored scan; writes nothing. `config.yaml` is edited by a person, exactly as with `iaiops tags apply`. **Every drafted field says whether the scan established it.** A field with `value: null` was NOT established, and its `caution` says what it is waiting for — do not fill one in and do not drop it. Dropping it lets the protocol default apply in silence, which is how a Modbus gateway gets read at unit 1 and shows a confident number…

  • onboarding_status

    [READ][risk=low] Where this site is on the path from a network to an answer. One altitude below `site_readiness`. That one lists every scenario and what each is waiting for; this one answers the smaller, earlier question a caller actually has first — **which journey this site is on, and which single command comes next** on it. There are two, with different first steps: devices — no UNS yet: scan → endpoints → point list → what each point MEANS → collect → ask the question uns — data already in an MQTT/UNS broker: connect → audit the namespace → choose …

  • opcua_alarm_events

    [READ][risk=low] Timestamped Alarms & Conditions via a bounded event subscription. Subscribes to the Server object for Condition-type events, optionally calls ConditionRefresh so currently-retained conditions are re-announced WITH their original event Time, listens for at most duration_s seconds, unsubscribes. The timed complement to opcua_read_alarms: each event carries the server's own timestamp, so RCA can time-localize alarm evidence. Requires a server that implements A&C event subscriptions (待核实 per server); an empty result can mean no events in the window OR no A&C support — pair with o…

  • opcua_anomaly_scan

    [READ][risk=low] Sample a node over a bounded window and flag statistical outliers. Computes mean/stddev/min/max and flags samples outside mean ± sigma*stddev. Simple statistics only — no ML, no persisted model. Args: node_id: The OPC-UA node id to scan. endpoint: Endpoint name from config. samples: Max samples (capped server-side). interval_ms: Delay between samples in milliseconds. sigma: Outlier band width in standard deviations.

  • opcua_browse

    [READ][risk=low] Browse the OPC-UA node tree from a node id (bounded depth). Args: node_id: Root node id (default i=85, the Objects folder). endpoint: Endpoint name from config. depth: Bounded browse depth (capped server-side).

  • opcua_diagnose_connection

    [READ][risk=low] Diagnose why an OPC-UA endpoint won't connect — a classified verdict. Attempts a connect (no writes, disconnects immediately) and classifies any failure into the well-known OPC-UA buckets instead of returning a raw error, each with a concrete next step: certificate (server doesn't trust our client cert) · auth (user/password) · security_policy (policy/mode mismatch) · port_closed · dns · firewall_timeout · unreachable · config (bad endpoint_url / connector not installed) · ok. Args: endpoint: Endpoint name from config; omit to use the default endpoint. Returns dict: {en…

  • opcua_discover_tags

    [READ][risk=low] Auto-discover OPC-UA tags and build a semantic asset model. Walks the address space, collects every Variable node, and enriches each with datatype / value / engineering-unit / a heuristic semantic class (temperature, pressure, flow, setpoint, alarm, state, …) and a suggested clean alias. Tags are grouped into assets by their browse path, and a naming-quality report flags alias collisions + cryptic names. Aliases are ADVISORY — nothing is written back to the server (a server-side rename would be OT-dangerous). Args: endpoint: Endpoint name from config; omit to use the def…

  • opcua_health_summary

    [READ][risk=low] Classify OPC-UA tag node-ids against warn/alarm thresholds. Returns ok/warn/alarm/unknown counts plus the offending tags; ``overall`` is never ``ok`` while any tag could not be judged, and ``coverage`` (complete|partial|none) says how many were. Thresholds come from config tags, or per-ref overrides in ``thresholds``. Args: endpoint: Endpoint name from config. node_ids: Tag node ids to evaluate; omit to use configured tags. thresholds: Optional {ref: {warn_high, alarm_high, warn_low, alarm_low}}.

  • opcua_read_alarms

    [READ][risk=low] Best-effort surfacing of active alarm/condition booleans (untimed). Browses the address space (bounded) for alarm-like boolean nodes reading True. Untimed by nature — for servers with A&C event support use opcua_alarm_events, which returns conditions WITH the server's timestamps. Args: endpoint: Endpoint name from config. node_id: Root node id to scan from (default i=85). depth: Bounded scan depth.

  • opcua_read_history

    [READ][risk=low] OPC-UA Historical Access (HDA): raw historical values over a window. Reads stored history for a node via the server's HistoryRead service, bounded by ``max_points``. Returns a clear 'unsupported' note when the server does not historize the node (no crash). Args: node_id: The OPC-UA node id to read history for (e.g. ns=2;i=5). endpoint: Endpoint name from config. start: ISO-8601 window start (default: 1 hour before end). end: ISO-8601 window end (default: now). max_points: Max points to return (capped server-side at 2000). Returns dict: {node_id, supporte…

  • opcua_read_many

    [READ][risk=low] Batch-read multiple node ids in one session (bounded count). Args: node_ids: List of OPC-UA node ids to read. endpoint: Endpoint name from config.

  • opcua_read_node

    [READ][risk=low] Read one node: value, datatype, source timestamp, status code. Args: node_id: The OPC-UA node id to read (e.g. ns=2;i=5). endpoint: Endpoint name from config.

  • opcua_server_info

    [READ][risk=low] OPC-UA server status, build info, and namespace array. Args: endpoint: Endpoint name from config; omit to use the default endpoint.

  • opcua_subscribe_sample

    [READ][risk=low] Sample a node a BOUNDED number of times, then return (never loops). Args: node_id: The OPC-UA node id to sample. endpoint: Endpoint name from config. samples: Max number of readings (capped server-side). interval_ms: Delay between readings in milliseconds. timeout_s: Hard wall-clock cap in seconds (capped server-side).

  • or_environment_check

    [READ][risk=low] Operating-room ventilation compliance (ASHRAE 170 Table 7.1). Grades each OR's environment — temperature 20–24 °C, relative humidity 20–60 %, air changes ≥ 20/hr — flagging any parameter out of range; each room takes the worst of its parameters, worst-first, citing every number. Pure analysis over readings you pass in (BACnet AI points / BMS); read-only, advisory. Complements isolation_room_check (pressure) with the OR air package. Args: rooms: [{room, temp_c?, humidity_pct?, air_changes_per_hour?}] — only the parameters present are graded. Returns dict: {rooms_…

  • pdm_forecast

    [READ][risk=low] Forecast a value's trend + time until it crosses a warn/alarm limit. The predictive step above baseline_check (which flags a violation that already happened): fits a robust Theil-Sen trend to the recent history and, if it continues, estimates the ETA to the nearest limit in the direction of travel — the early warning that makes maintenance predictive (inverter/turbine degradation, bearing drift, filter clogging). Refuses thin history; read-only, pure over the provided series; no device I/O. Beyond the trend, the result deepens into three explainable, stdlib-only views: a deg…

  • pharma_water_check

    [READ][risk=low] Grade PW / WFI loop readings — the stage-1 procedure, your limits. The water edition speaks the right protocols for a pharmaceutical water system (Modbus on the still and the skid, HART on the conductivity and TOC transmitters, OPC-UA on plant SCADA) but its semantics are municipal — DO, ORP, turbidity, chlorine. A purified-water loop is judged on conductivity, TOC and loop temperature, by a procedure that is easy to run backwards. Two parts of it are what this tool is for: **Stage 1 uses the NON-temperature-compensated reading**, and the measured temperature is rounded DOWN…

  • plc_program_drift

    [READ][risk=low] Has this program changed since its approved snapshot, and what moved? Three verdicts, and the wording of each is load-bearing. **identical** means the same SHA-256 and nothing else earns the word. **logic_changed** means the extracted structure differs — reported per block, naming which categories (variables / calls / branches / timers_counters) moved. **changed_outside_ extracted_structure** means the bytes differ while every block fingerprint matched: usually comments or formatting, but these parsers extract structure rather than parse a grammar, so a real change inside a c…

  • plc_program_history

    [READ][risk=low] Tracked programs, or one program's snapshot history. Local read of the program-baseline store — no file is parsed and no device is touched. Nothing is ever pruned automatically: a change-control history that quietly drops last quarter's baseline is worse than one that grows, and a stored row is block names, hashes and counts rather than source. Removing history is a deliberate act and is CLI-only (`iaiops program forget`) — deleting change-control evidence should not be one tool call away. Args: name: Tracked program name. Omit for the list of every tracked program. Ret…

  • plc_program_outline

    [READ][risk=low] Structural outline of an EXPORTED PLC program file. Parses one exported text file (Siemens SCL/ST .scl/.st, AWL/STL .awl, Rockwell Studio 5000 .L5X — .txt is content-sniffed) and returns blocks (FB/FC/OB/DB/routines/AOIs) with VAR sections, IF/CASE branch inventory, timers/counters, and the call graph. Never uploads from a live PLC; reads exactly the named file (≤5 MB). Every element cites source_file + line (rung number for L5X ladder) — quote those citations when explaining. Malformed sections degrade to entries in parse_errors, never a crash. Args: path: Exported prog…

  • plc_program_section

    [READ][risk=low] Source text of ONE named block from an exported program. Returns the exact source of a single block (FB/FC/OB/DB name for SCL/AWL; Program.Routine or routine name for L5X — rungs are rendered as '[rung N] ...'), capped at 200 lines with an explicit truncated flag, so the agent reads exactly the section it is explaining instead of guessing. Unknown block names fail with the list of available blocks. Args: path: Exported program file (.st/.scl/.awl/.l5x/.txt; must exist, ≤5 MB), under $IAIOPS_HOME, the config dir or an IAIOPS_AGENT_READ_DIRS dir. block: Block/r…

  • plc_program_snapshot

    [READ][risk=low] Record an exported program's structure as a change baseline. A control program is a controlled document, and the usual way an undocumented change to one gets noticed is that somebody remembers. This gives the comparison a number: the file's SHA-256, plus a per-block structural fingerprint (name/kind/language, declared variables, calls, branch conditions, timers) that deliberately excludes line numbers, comments and block order — so adding a comment at the top of a file does not report the whole program as changed. Stored locally under the iaiops home as block names, hashes an…

  • plc_program_visibility

    [READ][risk=low] Maintainability / operational-risk profile of a legacy PLC program. The "what am I inheriting?" view over one EXPORTED program (SCL/ST, AWL/STL, Rockwell L5X): folds the structural outline into documentation coverage, the least-commented blocks, blocks nothing references (possible dead code), the complexity hotspots, risky constructs (unconditional JMPs, retentive RTO timers, loops), and a TRANSPARENT additive risk score whose every point cites its reason. Structural only — it anchors an engineer's review of a line somebody else left behind, not a semantic understanding. Read…

  • plc_program_xref

    [READ][risk=low] Cross-reference one symbol in an exported PLC program. Finds every read/write/call/declare site of a symbol or absolute address (e.g. Motor_Run, "FB_Conveyor", DB10.DBX0.1, M0.0, Tank[2].Level) in one exported file, quoting the surrounding source line verbatim so the agent cites real code. Access classification is heuristic (op/regex based, not data-flow analysis): SCL ':='→write, '('→call; AWL T/=/S/R→write, L/A/O…→read, CALL→call; L5X OTE/OTL/OTU/RES and MOV-dest→write. For L5X, line is the rung number. Args: path: Exported program file (.st/.scl/.awl/.l5x/.txt; must e…

  • plc_program_xref_config

    [READ][risk=low] Join an exported program's addresses with one endpoint's configured points. Answers "which program symbol is that point on the line?" by **exact address match only** — never by name. A configured label that reads like a program symbol, or a ref one character from a tag, is NOT a match (semantics are given by a person, never guessed). Comparable pairs: Siemens AWL / .scl × an ``s7`` endpoint (area, DB, byte, bit and width must all agree) and Rockwell L5X × a Logix ``ethernetip`` endpoint (the tag path is the CIP address). Every other pair returns ``comparable: false`` with the…

  • profinet_asset_inventory

    [READ][risk=low] PROFINET asset register from a DCP IdentifyAll sweep. Segment-wide, read-only — no per-device connection. The DCP device-role bitmask is decoded when the client exposes it; pnio-dcp does not, so roles and the controller/device counts come back empty and 0. Names, MACs and IP suites are unaffected — those are what the register is for. Args: endpoint: Endpoint name from config (protocol 'profinet'). Returns dict: {endpoint, asset_count, io_controller_count, io_device_count, assets:[{name_of_station, mac, ip, vendor_id, device_id, roles[], family}], method:'dcp_ide…

  • profinet_dcp_set

    [WRITE][risk=HIGH][MOC] DCP Set — re-address one PROFINET station (off by default). OT-DANGEROUS. Defaults to dry_run=True (nothing set). Re-addresses a live station's name-of-station and/or IP suite via a unicast DCP Set (can disrupt the IO connection). Captures the BEFORE addressing (by MAC) and records an undo descriptor. Set dry_run=False AND record an approver (OPCUA_AUDIT_APPROVED_BY) to apply. 未经授权勿对生产控制系统写入. Args: mac: Target station MAC, e.g. '00:1b:1b:12:34:56' (from profinet_discover). set_name: New name-of-station (omit to leave unchanged). set_ip: New IP address (omi…

  • profinet_discover

    [READ][risk=low] DCP IdentifyAll — every PROFINET station on the segment. One layer-2 broadcast surfaces all stations without connecting to any. Needs raw-socket access on the NIC on the PROFINET subnet (pnio-dcp extra); degrades to a teaching error dict when pnio-dcp/permission/NIC is missing. Args: endpoint: Endpoint name from config (protocol 'profinet'); omit for default. Returns dict: {endpoint, local_ip, station_count, stations:[{name_of_station, mac, ip, netmask, gateway, vendor_id, device_id, device_role_raw, device_roles[], device_family}]}. vendor_id/device_id/device_r…

  • profinet_identify_station

    [READ][risk=low] Identify one station by its PROFINET name-of-station. Args: name_of_station: Exact (case-insensitive) PROFINET station name, e.g. 'plc1'. endpoint: Endpoint name from config (protocol 'profinet'). Returns dict: {endpoint, found (bool), name_of_station, mac, ip, netmask, gateway, vendor_id, device_id, device_roles[], device_family}. Example: profinet_identify_station(name_of_station="et200sp-1", endpoint="cell1").

  • profinet_station_params

    [READ][risk=low] Targeted DCP Get for one station (by MAC): name + IP suite. Args: mac: The station's MAC address, e.g. '00:1b:1b:12:34:56'. endpoint: Endpoint name from config (protocol 'profinet'). Returns dict: {endpoint, mac, found (bool), name_of_station, ip, netmask, gateway}. Example: profinet_station_params(mac="00:1b:1b:12:34:56", endpoint="cell1").

  • protocols_supported

    [READ][risk=low] Capability map — protocols, status, tools, connection params. Call this to discover what iaiops can do before choosing a protocol/tool. Lists implemented protocols (OPC-UA incl. HDA, Modbus, S7comm, Mitsubishi MC, MTConnect, MQTT/Sparkplug B full-decode, EtherNet/IP Logix) and the EtherCAT roadmap stub, plus cross-protocol analytics (OEE/downtime, asset inventory, CoV), each with its read/write tools and the endpoint params it needs. Also reports whether this server runs under the no-egress gate, so a model is TOLD the posture instead of having to infer it from tools it cann…

  • pv_performance

    [READ][risk=low] Flag underperforming PV strings vs expected (or fleet-median) output. Which strings / inverters are underperforming, and by how much? A string that lags its peers (or its irradiance-expected output) is the signature of soiling, shading, a blown fuse, or a failed module. Computes each string's performance ratio against its expected output — ``expected_w`` if given, else nameplate × irradiance/1000, else the fleet median — and flags laggards below the threshold. Worst-first, each ratio cited by its inputs. Pure analysis over readings you pass in (inverter/combiner Modbus or pla…

  • rca_corpus_from_maintenance

    [READ][risk=low] Turn a CMMS/work-order export into the RCA incident corpus. Auto-builds the labeled history learn_cause_weights needs from closed maintenance records: an explicit taxonomy cause column wins; else a built-in EN/中文 CMMS synonym table (extendable via 'synonyms'); else UNAMBIGUOUS keyword inference over the row's free text using the copilot's own cause keywords. Rows it cannot map land in 'unmapped' with the reason — never silently guessed. 'signals' come from an explicit column or the symptom/alarm text (may stay empty — no fabricated evidence). Pure + advisory; with learn=true …

  • rca_narrate

    [READ][risk=low] Narrate a cited RCA verdict in plain language via an on-box LLM. Air-gapped: hands the already-computed, already-cited verdict to a LOCAL model (Ollama) that ONLY rephrases it — it never adds a cause, number, or citation (strict prompt; see docs/RCA.md). Read-only; no device I/O. Needs the extra + a running local model: pip install iaiops[ollama]. Args: verdict: An RCA verdict dict (e.g. the output of downtime_root_cause). base_url: Ollama server URL (default http://localhost:11434). model: Local model name (default 'llama3.1'). provider: LLM provider (curren…

  • s7_cpu_info

    [READ][risk=low] S7 CPU identity + run/stop status (proves the link). Args: endpoint: Endpoint name from config (protocol must be 's7'); omit for default. Returns dict: {endpoint, rack, slot, cpu_status (e.g. 'run'/'stop'), cpu_info: {module, serial, version, ...}}. Example: s7_cpu_info(endpoint="press1").

  • s7_read_area

    [READ][risk=low] Read ``count`` items of a type from an S7 memory area. Args: area: Memory area — DB | M (merker/flag) | I (input) | Q (output). dtype: S7 data type — BIT|BYTE|WORD|INT|DWORD|DINT|REAL|LREAL|CHAR. start: Byte offset within the area/DB (0-based). endpoint: Endpoint name from config. db: Data block number (required when area=DB). count: Number of consecutive items (1..100, capped server-side). bit: Bit offset 0..7 (only when dtype=BIT). Returns dict: {endpoint, area, db, dtype, start, count, items:[{address, value}]}. ``value`` is bool/int/float …

  • s7_read_db

    [READ][risk=low] Read ``count`` ``dtype`` items from data block ``db``. Args: db: Data block number (e.g. 1 for DB1). dtype: S7 data type — BIT|BYTE|WORD|INT|DWORD|DINT|REAL|LREAL. start: Byte offset within the DB (0-based). endpoint: Endpoint name from config. count: Number of consecutive items (1..100). Returns dict: {endpoint, area:'DB', db, dtype, start, count, items:[{address, value}]}. Example: s7_read_db(db=1, dtype="INT", start=0, count=10).

  • s7_read_many

    [READ][risk=low] Batch-read raw pyS7 address strings in one request. Args: addresses: pyS7 addresses, e.g. ["DB1,REAL4", "DB1,X0.0", "MW10", "I0.0"]. endpoint: Endpoint name from config. Returns dict: {endpoint, count, items:[{address, value}]}. Example: s7_read_many(addresses=["DB1,REAL4","M0.0"]).

  • s7_write_db

    [WRITE][risk=HIGH][MOC] Write ONE value to an S7 data block (off by default). OT-DANGEROUS. Defaults to dry_run=True (nothing written). Captures the BEFORE value (read-back) and records an undo descriptor so the change is reversible. Set dry_run=False AND record an approver (OPCUA_AUDIT_APPROVED_BY) to apply. 未经授权勿对生产控制系统写入. Args: db: Data block number. dtype: S7 data type — BIT|BYTE|WORD|INT|DWORD|DINT|REAL|LREAL. start: Byte offset within the DB. value: Value to write (coerced to the dtype's Python type). endpoint: Endpoint name from config. dry_run: When True (defa…

  • secsgem_equipment_status

    [READ][risk=low] Establish the GEM host link and report communication state + identity. Sends Are-You-There (S1F1) after reaching the communicating state. Args: endpoint: Endpoint name from config; omit to use the default endpoint.

  • secsgem_list_alarms

    [READ][risk=low] Alarm list (S5F5/F6): ALID, ALCD (severity), alarm text. Args: endpoint: Endpoint name from config.

  • secsgem_list_equipment_constants

    [READ][risk=low] Equipment-constant namelist (S2F29/F30): ECID → name/min/max/default. Args: endpoint: Endpoint name from config.

  • secsgem_list_process_programs

    [READ][risk=low] Process-program directory (S7F19/F20): the PPID list. Args: endpoint: Endpoint name from config.

  • secsgem_list_status_variables

    [READ][risk=low] Status-variable namelist (S1F11/F12): SVID → name / units. Args: endpoint: Endpoint name from config.

  • secsgem_read_equipment_constants

    [READ][risk=low] Equipment-constant values (S2F13/F14) for the given ECIDs. Args: ecids: List of equipment-constant ids to read. endpoint: Endpoint name from config.

  • secsgem_read_status_variables

    [READ][risk=low] Status-variable values (S1F3/F4) for the given SVIDs. Args: svids: List of status-variable ids to read. endpoint: Endpoint name from config.

  • sensor_import_iodd

    [READ][risk=low] Draft a sensor profile from a vendor IODD file. Writes nothing. The draft is marked ``verified: 待核实``: IODD unit codes are kept as codes, signal kinds are assumed (and say so), and every item that could not be represented is listed in ``notes``. Save the draft, replace the unit codes with real units, check one live reading, then bind it under ``port_profiles`` in config.yaml yourself — this tool never edits config. Args: path: The device's IODD (.xml), under $IAIOPS_HOME, the config directory or an IAIOPS_AGENT_READ_DIRS directory — other paths are refuse…

  • sensor_profile_check

    [READ][risk=low] Validate a sensor profile file and list its channels. Args: path: A profile (.yaml / .yml), under $IAIOPS_HOME, the config directory or an IAIOPS_AGENT_READ_DIRS directory — other paths are refused unread. Returns dict: {id, protocol, source, verified, match, pd_bits, channels:[{channel, layout, unit, signal, range, sentinels, band}]}. An invalid profile returns {error} naming the field.

  • sensor_profile_list

    [READ][risk=low] List the shipped sensor profile library (HLD §17.3). Entries are ``verified: 待核实`` unless they carry provenance evidence. For an IO-Link device, pass the vendor/device id read with ``iolink_device_info`` to find candidates — a match is a SUGGESTION: one device id can run several process-data layouts, and binding stays a person's edit of config.yaml. Args: protocol: modbus | iolink (optional). vendor_id: IO-Link vendor id (optional). device_id: IO-Link device id (optional). Returns dict: {profiles:[{id, category, protocol, verified, source, description, cavea…

  • sensor_profile_show

    [READ][risk=low] Show one library profile: summary plus its YAML text. Writes nothing. To use it, a person saves the YAML, checks one reading against the device's own display, and binds it in config.yaml. Args: profile_id: An id from ``sensor_profile_list``. Returns dict: {summary (as sensor_profile_check), yaml, next}; {error, known} for an unknown id.

  • sensor_read_channel

    [READ][risk=low] Read one sensor point once and say how far it got. Levels are reported separately and never upgraded: ``reachable`` (did the device answer — a Modbus exception or an IO-Link "different device" answer counts as answered; None when nothing was contacted) and ``decodable`` (did the answer decode into a measurement — None when the device never answered). Only when both are true are value, unit, accuracy band and the profile's verification level returned. A ref the endpoint cannot read is refused before contacting anything. Nothing is stored. Args: ref: ``ch:<name>`` (Modbus …

  • serial_sniff

    [READ][risk=low] Listen on a serial instrument and return its raw lines. Sends nothing — not even a poll query — and needs no profile: it is how a profile's pattern is written. The port is opened exclusively and a port in use by another program is refused, never taken (D53). Bounded: at most 30 s and 200 lines; lines are shown in latin-1 so every byte is visible. Args: endpoint: Serial endpoint name from config (default endpoint if omitted). seconds: How long to listen (0.1–30). max_lines: Stop after this many lines (1–200). Returns dict: {endpoint, seconds, lines[], note}.

  • site_readiness

    [READ][risk=low] Which scenarios THIS site can run today, and what each gap needs. The companion to `protocols_supported`, one altitude down. That one says what the product can do; this says what this installation can do — and calling the first without the second is how an agent plans a scenario the site has no inputs for. Contacts nothing: no device, no network, no historian. It is derived from `config.yaml` and the local store, which is what makes it runnable against a site nobody has authorised you to probe — the site that most needs it. Three states, and the middle one carries the value…

  • sortation_health

    [READ][risk=low] Sorter read-rate / no-read / mis-sort analysis. Are packages being read and diverted to the right chute? Over per-sort divert records it derives the three rates a DC operator watches — read rate, no-read rate, mis-sort rate — against targets, and ranks the chutes receiving the most mis-sorts (a jammed diverter or a mis-mapped chute). Pure analysis over records you pass in (WCS / sorter PLC event log); read-only, each rate cited by counts. Args: sorts: [{read (bool), assigned_chute, actual_chute}] — one per item across the sorter. Mis-sort = a READ item whose actu…

  • sparkplug_decode_payload

    [READ][risk=low] Decode a single raw Sparkplug B payload to structured metrics. Full protobuf decode (vendored Eclipse Tahu schema): per metric returns name, alias, datatype (Int/Float/Bool/String/DateTime/DataSet/Template…), value, timestamp, and is_historical / is_null flags. Rich types expand: a DataSet value decodes to {columns, types, rows} and a Template value to {template_ref, is_definition, version, members, parameters} (members decoded recursively). Args: payload: Raw Sparkplug B protobuf bytes as a string, ``base64`` (default) or ``hex``. encoding: 'base64' or 'hex'. al…

  • sparkplug_live_schema

    [READ][risk=low] Capture a LIVE Sparkplug schema (bounded) → drift-ready dict. Subscribes, collects up to ``max_msgs`` messages or until ``duration_s``, decodes NBIRTH/DBIRTH metrics, and returns ``schema`` = {node: {metric: datatype}} (node = group/edge[/device]) — exactly the shape uns_schema_drift accepts. Use it as a baseline or current snapshot. Args: endpoint: Endpoint name from config. topic: Topic filter (default 'spBv1.0/#'). duration_s: Capture window in seconds (1..60). max_msgs: Max messages to capture (1..500). Returns dict: {endpoint, topic, message_count, birt…

  • sparkplug_node_list

    [READ][risk=low] Discover edge nodes/devices + online state + primary-host STATE. Builds the birth/death + seq model from BIRTH/DATA/DEATH/STATE topics: each node reports online/born, its devices, learned metric aliases, and seq gaps; STATE topics surface primary-host status. Args: endpoint: Endpoint name from config. timeout_s: Observation window in seconds (1..60). Longer catches infrequent nodes. count: Max messages to inspect (1..500). Returns dict: {endpoint, node_count, nodes:[{group_id, edge_node_id, online, born, devices:[...], metric_aliases_known, seq_gap_count, se…

  • sparkplug_subscribe_sample

    [READ][risk=low] Bounded Sparkplug B sample with full decode + birth/death/seq. Topics are parsed and payloads fully protobuf-decoded; a birth/death + seq model resolves aliases (from NBIRTH/DBIRTH), applies NDATA/DDATA by alias, and flags is_historical metrics and seq gaps. Args: endpoint: Endpoint name from config. topic: Topic filter (default 'spBv1.0/#'). count: Max messages (1..500). timeout_s: Max seconds to wait (1..60). Returns dict: {endpoint, topic, message_count, historical_metric_count, seq_gap_count, samples:[{topic, sparkplug:{group_id, message_type, ed…

  • spc_check

    [READ][risk=low] SPC control-chart rule check (Western Electric / Nelson). Is a measurement series in statistical control, or is something special-cause happening? Centers on the process mean (or a target), estimates sigma (or uses a supplied one), and applies the standard rules — a point beyond 3σ, 2-of-3 beyond 2σ, 4-of-5 beyond 1σ, 8-in-a-row one side, 6-point trend — reporting each violation by point index. With spec limits it adds Cp / Cpk. Pure analysis over the series you pass in; read-only, advisory (each hit cited by its index). Args: series: Measurements — scalars or {value}. …

  • stream_publish

    [READ][risk=low] Publish already-read normalized points to a message bus (NATS). Egress of data the agent already READ — NOT a control write. Each numeric point becomes a JSON message on ``<subject_prefix>.tag.<metric>``; non-numeric points are skipped (use a historian sink for text/state). Needs the extra: pip install iaiops[nats]. Args: points: Collected point dicts (e.g. from *_read_many): {ref/metric, value, timestamp, ...}. subject_prefix: NATS subject root (default 'iaiops'). servers: Comma-separated NATS server URLs (default nats://localhost:4222). token: Optional NATS…

  • stream_publish_event

    [READ][risk=low] Publish one computed event (RCA verdict / alarm) to a message bus (NATS). Egress of a finding the brain already COMPUTED — e.g. an RCA verdict or an alarm episode — to ``<subject_prefix>.<subject>`` as JSON. NOT a control write. Needs: pip install iaiops[nats]. Args: subject: Event subject suffix (e.g. 'rca.verdict', 'alarm.flood'). event: The event payload dict (published as JSON). servers/token/tls/subject_prefix/publisher: bus connection (see stream_publish). Returns dict: {publisher, subject, published}. Example: stream_publish_event(subject="rca.verdict", …

  • subscription_health

    [READ][risk=low] Health of a sequenced subscription feed (OPC-UA or Sparkplug B). Detects dropped notifications (sequence gaps), duplicates / out-of-order, a high republish-rejection rate, and overloaded channels — the classic Kepware "too many tags on one channel → republish/queue-flush dropouts" fault. Args: sequence: Sequence numbers actually received, in arrival order. republish_requested: How many republish requests were made. republish_rejected: How many were rejected (server couldn't keep up). tags_per_channel: {channel/endpoint: tag_count} — flags channels over the ma…

  • tag_health

    [READ][risk=low] Rank tag offenders by bad-quality / flatline / range / anomaly. Args: tags: Per-tag dicts — {ref, label?, samples:[scalars or {value, good|quality}], warn_high?, alarm_high?, warn_low?, alarm_low?}. thresholds: Optional {ref: {warn_high, alarm_high, warn_low, alarm_low}} override. Returns dict: {evaluated, overall ('ok'|'warn'|'alarm'), offender_count, offenders:[{ref, label, samples, latest, flags:[...], anomaly_count, severity (0..3)}], results:[...]}. Flags include bad_quality, flatline, out_of_range_warn/alarm, statistical_anomaly. Example: t…

  • uns_browse

    [READ][risk=low] Browse the live topic tree (UNS) under a filter (bounded). Args: endpoint: Endpoint name from config. topic: Topic filter to browse under (default '#'). timeout_s: Observation window in seconds (1..60). count: Max messages to inspect (1..500). Returns dict: {endpoint, filter, topic_count, topics:[...], tree:{nested segments}}. Example: uns_browse(topic="factory/#", timeout_s=8).

  • uns_live_audit

    [READ][risk=low] Capture the LIVE UNS topic tree (bounded) then audit it. Closes the governance loop: subscribes to a live broker, collects up to ``max_msgs`` messages or until ``duration_s`` (whichever first), then runs the naming-conformance + topic-sprawl audit over the observed topics. Never an open-ended loop. Args: endpoint: Endpoint name from config (protocol must be 'mqtt'). topic: Topic filter to capture under (default '#'). duration_s: Capture window in seconds (1..60, capped server-side). max_msgs: Max messages to capture (1..500, capped server-side). allowed_r…

  • uns_live_drift

    [READ][risk=low] Capture the LIVE Sparkplug schema (bounded) and diff vs baseline. Captures current node/metric definitions from live BIRTHs, then runs schema drift against ``baseline`` — added / removed / type-changed metrics per node with a none/additive/breaking verdict. Args: baseline: Prior schema {node:{metric:datatype}} (e.g. from sparkplug_live_schema). endpoint: Endpoint name from config. topic: Topic filter (default 'spBv1.0/#'). duration_s: Capture window in seconds (1..60). max_msgs: Max messages to capture (1..500). Returns dict: the uns_schema_drift result …

  • uns_publish

    [READ][risk=low] Publish already-read normalized points to an MQTT broker / UNS. Egress of data the agent already READ — NOT a control write. Each numeric point becomes a JSON message on ``<topic_prefix>/<metric>``, with a dotted metric nested into topic levels (``line1.temp`` -> ``plant/line1/temp``) so a Unified Namespace stays browsable. Non-numeric points are skipped (use a historian sink for text/state). The topic is always derived from ``topic_prefix`` — it is never taken verbatim, so this cannot address a command topic. Needs the extra: pip install iaiops[mqtt]. Args: points: Coll…

  • uns_schema_drift

    [READ][risk=low] Detect Sparkplug/UNS schema drift between two snapshots. Compares baseline vs current node/metric definitions (e.g. two NBIRTH snapshots) and reports added / removed / type-changed metrics per node, with a verdict. Args: baseline: {node: {metric: datatype}} or [{node|topic, metrics:[{name, datatype}]}]. current: Same shape — the newer snapshot to compare against the baseline. Returns dict: {baseline_nodes, current_nodes, changed_nodes, verdict ('none'|'additive'|'breaking'), node_changes:[{node, node_status, added[], removed[], type_changed:[{metric, from, t…

  • uns_topic_audit

    [READ][risk=low] Govern a UNS topic tree: naming conformance + topic sprawl. Pure analysis over a provided list of UNS topic strings (no live broker). Flags non-conforming roots, too-shallow topics, casing collisions of the same logical name, leaf metrics scattered under many parents, depth outliers, and duplicates. Args: topics: UNS topic strings, e.g. ["Enterprise/Site/Area/Line1/temperature", ...]. allowed_roots: Permitted top-level segments; others are flagged (optional). min_segments: Minimum namespace depth a well-formed topic must have. max_leaf_parents: A leaf appeari…

  • verify_determinism

    [READ][risk=low] Prove this engine's analysis is reproducible without a model. Runs a named suite of analyses (availability, production counts, the Six Big Losses, ISA-18.2 alarm load, control charts, the conservative baseline, the RCA copilot) over a pinned reference dataset, canonically encodes each result and digests it — twice in this process and, with ``subprocesses``, once more in each of two fresh interpreters started at different PYTHONHASHSEED values. That last arm is the one that catches a set or dict iteration order reaching a result; a single run never can. The socket API raises t…

  • water_quality_compliance

    [READ][risk=low] Grade finished-water readings against drinking-water limits. The continuous-compliance companion to disinfection_ct: grades turbidity (filtration/pathogen surrogate), free chlorine residual (too low = under- disinfected, too high = taste/DBP) and pH per sample point. Defaults — turbidity ≤ 1.0 NTU, free chlorine 0.2–4.0 mg/L, pH 6.5–8.5 — are overridable per the utility's permit. Each point takes the worst of its parameters, worst-first, citing every number. Pure analysis over readings you pass in (Modbus/HART analyzers or OPC-UA SCADA); read-only, advisory. Args: points…

  • zone_comfort

    [READ][risk=low] Occupied-zone comfort + IAQ vs ASHRAE 55 / 62.1. The #1 building-complaint driver: grades each zone's temperature (20–26 °C), relative humidity (30–60 %) and CO₂ (≤ 1000 ppm, a ventilation-adequacy proxy), flagging any parameter out of range; each zone takes the worst of its parameters, worst-first, citing every number. Pure analysis over readings you pass in (BACnet AI points); read-only, advisory. Args: zones: [{zone, temp_c?, humidity_pct?, co2_ppm?}] — only the parameters present are graded. Returns dict: {zones_evaluated, standard, summary, breach_count, …

Signals

Stars
7
Forks
0
Open issues
0
Weekly downloads
898
Last commit
Oct 19, 2026 (7 days ago)
Last release
Oct 19, 2026 (7 days ago)
Last package publish
Oct 19, 2026 (7 days ago)

From GitHub (fetched Oct 24, 2026) and the package registry.

Details

Registry name
io.github.industrial-aiops/iaiops
Version
0.32.0
Auth
API key
Packages
pypi iaiops
License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from industrial-aiops

Cite this page

Industrial-AIOps MCP server. Agent Mart. https://agentmart.dev/connectors/industrial-aiops-iaiops (last updated 2026-10-24)