a.williamson d353c5001e Data seeding, filter overhaul, UI scaling fixes, sanitized AlarmAnalysis copy
Data & simulation:
- simulation_tags.json: re-prioritize 10 tags to Medium so all four
  priorities appear in live data (backfilled journal history to match)
- SimHarness probe P2: ack-user/includeData ground truth + filtered-bundle
  verification against the live journal

Data layer (PrimeControls.calc/alarms):
- filters now drive every metric: queryStatus rows (Active Now/Unacked/
  Standing) filtered via calc.apply_status_filters; event_count counts only
  filtered instances (per-instance n_events); dropdown options enumerate
  unfiltered data so choices never collapse
- build_bundle refactored into _assemble(); when filters are active an
  unfiltered mirror is attached as bundle.overview - the Overview tab stays
  a plant-wide summary while all other consumers bind filtered sections
- _fetch_journal now honors includeData (required for ackUserName; without
  it ack attribution is always None); enabled for journal rows + source
  detail so Top Ack Users and the Ack By column populate

FilterBar/Dashboard:
- root-cause fix: bidirectional bindings never wrote dropdown selections
  back to session props, so filters silently did nothing; Apply now pulls
  values directly from the sibling controls, Clear resets both
- multi-select dropdowns cap at 280px and wrap chips; filter bar row is
  auto-height so wrapped chips push tabs down instead of overlapping
- filter bar hidden on the Overview tab (not applicable there)

UI scaling:
- Header: Prime logo added; KpiCard compacted to fit the 71px KPI row
  (basis-95% overflow fix, chip hugs text, embeds clipped) - no scrollbars
- Overview timeline: thinned x labels (minDistance 140), labels anchored
  below the axis, smaller legend markers
- Bad Actors focus chip shows the full source string with the clear X
- popup repeaters (Daily Activity, ScoreBars) no longer overflow
  (useDefaultViewWidth/Height off, taller strip); 5px table cell padding

Tooling/tests:
- lint_project.py: accept propConfig params.* as param declarations
  (Designer saves strip null params entries)
- tests: 31 -> 34 (status-filter semantics, overview mirror, filtered
  event counts)
- .gitignore: runtime churn (valueStore.idb, local-system-properties,
  migration logs, thumbnails, .schemas)

New project: AlarmAnalysis - submission copy of PrimeBAT with client-visible
Prime Controls branding removed (logo, subtitle, project title, shift report
heading); PrimeControls organizational namespaces retained per spec.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 16:27:48 -05:00

Build-a-Thon — Alarm Analysis Dashboard (Ignition 8.3.7 + Perspective)

Local development environment for the Inductive Automation Build-a-Thon. Native Ignition features only — no third-party modules (contest rule).

Quickstart

docker compose up -d
  • Gateway: http://localhost:8088 — login admin / password
  • MariaDB: localhost:3306 — db ignition, user ignition / ignition (root password: password)

First start takes a minute or two while the gateway commissions itself (EULA, edition, and admin credentials are seeded by env vars, so there is no commissioning wizard). Watch with:

docker compose logs -f ignition

The gateway is ready when curl http://localhost:8088/StatusPing returns {"state":"RUNNING"}.

Gateway state lives in this repo (gateway-as-files)

The gateway's durable state is bind-mounted from the repo (primebench/TestingPlatform pattern) — a container recreate can never wipe it, and the gateway never re-commissions:

Repo path In container (data/) What's in it
ignition/gateway/commission/commissioning.json commissioning.json Commissioning marker (committed)
ignition/gateway/config/ config/ All config resources: DB connection, journal, API token, tags, secrets
ignition/gateway/projects/ projects/ Project files: Perspective views, scripts, timers

Everything else (internal db, logs, certs) stays ephemeral in the container. The gateway runs as your host uid/gid (IGNITION_UID/IGNITION_GID, default 1000), so files stay owned by you.

Edit-files workflow: change files under ignition/gateway/, then tell the gateway to reload — python3 tools/provision.py scan-config (config/tags) or scan-projects (project resources). Changes made in the Designer/gateway UI land back in these files, ready to diff.

Automated provisioning (REST API)

Gateway config is provisioned through the Ignition 8.3 HTTP API using tools/provision.py (stdlib only, no pip installs). On a fresh gateway:

python3 tools/provision.py mint-token   # API token file-drops + gateway restart; updates .env
python3 tools/provision.py provision    # secret provider + DB connection + alarm journal + sim tags
  • mint-token writes an api-token config resource under ignition/gateway/config/, patches the Authenticated > API security levels into gateway read/write permissions, restarts the gateway (if running; otherwise the token loads on next boot), and saves IGN_API=Buildathon:<secret> to .env (gitignored). Only the SHA-256 hash of the secret is stored in the config files.
  • provision is idempotent — it skips resources that already exist. It creates:
    • file secret provider local (MariaDB password lives in the gitignored file ignition/gateway/config/secrets/mariadb_password, referenced by the connection — the 8.3 API only accepts encrypted or referenced secrets)
    • database connection Buildathon_DBjdbc:mariadb://db:3306/ignition
    • alarm journal Journal → tables PrimeControls_alarm_events / PrimeControls_alarm_event_data
    • imports test-data/simulation_tags.json into the default tag provider

Ad-hoc API calls use one header: curl -H "X-Ignition-API-Token: $IGN_API" $GATEWAY_URL/openapi.json (source .env first).

Two steps remain manual (Designer-only): creating the Buildathon Perspective project (step 3 below) and installing the simulator timer script (test-data/README.md).

Manual setup reference (what provision.py does, plus the Designer steps)

1. Database connection (MariaDB) — automated

Gateway web UI → Config → Databases → Connections → Create new Database Connection

Setting Value
Name Buildathon_DB
Driver MariaDB
Connect URL jdbc:mariadb://db:3306/ignition
Username ignition
Password ignition

Note the host is db (the compose service name), not localhost — the gateway reaches MariaDB over the compose network. Save and confirm the status shows Valid.

Ignition 8.3 ships the MariaDB JDBC driver, so no driver install is needed.

2. Alarm journal profile — automated

Gateway web UI → Config → Alarming → Journal → Create new Alarm Journal Profile

Setting Value
Name Journal (any name works)
Type Database
Datasource Buildathon_DB
Table prefix PrimeControls_

Leave the event filters at defaults (store everything) so the analytics have full data. The journal auto-creates PrimeControls_alarm_events and PrimeControls_alarm_event_data in MariaDB the first time an alarm event occurs.

3. Perspective project — manual

  1. Gateway web UI → Config → Projects → Create new Project (or Designer → File → New Project)
    • Name: Buildathon
  2. Open it in the Designer (launch from http://localhost:8088 → Designer launcher), then set the project default database: Project → Project Properties → General → Default DatabaseBuildathon_DB. Save the project.

Named queries and bindings that use the "default" database now hit MariaDB.

Test data

See test-data/README.md — imports simulation memory tags with alarm configs and a Jython script that generates realistic alarm activity (baseline alarms across 5 plant areas / 3 priorities, chattering, standing, fleeting, and flood-burst patterns).

Reset to a completely fresh gateway

Gateway state is repo files now, so docker compose down -v alone no longer wipes the gateway — it only removes the containers and the MariaDB volume. To verify the project export imports cleanly on a fresh install (the contest judging scenario), set the gateway files aside and rebuild:

docker compose down -v                    # containers + MariaDB volume
mv ignition/gateway ignition/gateway.bak  # keep your current state for rollback
mkdir -p ignition/gateway/commission ignition/gateway/config ignition/gateway/projects
cp ignition/gateway.bak/commission/commissioning.json ignition/gateway/commission/
docker compose up -d                      # boots factory-fresh, auto-commissions
python3 tools/provision.py mint-token     # old token lived in gateway.bak
python3 tools/provision.py provision

Then import your project export to prove it stands alone. Roll back to your working state with docker compose down && rm -rf ignition/gateway && mv ignition/gateway.bak ignition/gateway && docker compose up -d (MariaDB journal data is gone either way after -v — the sim regenerates it).

A plain docker compose down / up -d restarts with everything intact.

Notes

  • Max JVM heap is 2 GB (-m 2048 runtime arg in the compose command).
  • The 8.3 image's data dir is /usr/local/bin/ignition/data; only commissioning.json, config/, and projects/ are bind-mounted from ignition/gateway/ (see the gateway-as-files section above).
  • ignition waits on the MariaDB healthcheck before starting, so the datasource is reachable as soon as the gateway is up.
Description
No description provided
Readme 5.6 MiB
Languages
Python 99%
CSS 0.6%
Shell 0.4%