Skip to content

CAMBER capabilities reference

A single index of what CAMBER does, grouped by the building-analytics layers, with the key API, the option flags that tune each capability, the module, and the standard it cites. Deeper write-ups are linked where they exist.

Everything is vendor-neutral via the Role model, dependency-light (stdlib + numpy / pandas / pyarrow / matplotlib), and clean-room (every method cites a public standard; every rule ships a synthetic fixture).

flowchart TD
  src["BAS sources (CSV/SQL/Haystack/Modbus/MQTT/BACnet/OPC-UA)"] --> ingest["Ingest (SourceAdapter)"]
  ingest --> model["Semantic model (Role + MappingProvider + entities)"]
  model --> fdd["FDD (rules.Registry)"]
  model --> mv["M&V (mandv change-point / TOWT)"]
  model --> stream["Streaming (OnlineFDD / OnlineCusum / forecast)"]
  model --> domain["Domain analytics (comfort/carbon/GEB/ventilation)"]
  fdd --> triage["Triage + lifecycle (rules.triage / faultlifecycle)"]
  triage --> advisory["Advisory (aso / actionplan / scorecard)"]
  mv --> report["Reporting (AuditReport / fleet)"]
  advisory --> report
  domain --> report
  report --> platform["Platform (store / api / integrate / plugins / charts)"]

The capability families, all speaking the vendor-neutral Role model.


Ingest

Adapters normalize any source to named point series on a common time grid (SourceAdapter: point_names / load_points / units). See INGEST-PROTOCOLS.md and SECURITY.md.

  • CSV — ingest.csv_perpoint.PerPointCsvAdapter (a folder of per-point files), ingest.csv_wide.WideCsvAdapter (one wide table), and ingest.csv_long.LongCsvAdapter (timestamp,point,value historian shape). Flags: resample, profile.
  • Vendor formats — one shared multi-format timestamp parser (tsparse: ISO / US / EU-dayfirst / BAS / epoch / Excel-serial) + value/status coercion (coerce: thousands, null tokens, On/Off/Open/ Closed/Fault status) + named vendor profiles (ingest.profiles: niagara_n4/metasys/webctrl/tracer/ desigo). load_csv(..., profile=…). See INGEST-FORMATS.md.
  • Project-Haystack — ingest.haystack.HaystackAdapter over an injectable transport (http_json_transport, or client_transport to wrap a maintained client). Flags: range_str, resample.
  • SQL / historian — ingest.sql.SqlSource / read_points over any PEP-249 connection. Flags: ts_col / point_col / value_col / unit_col, where.
  • Network protocols (read-only) — Modbus ([modbus]), MQTT/Sparkplug ([mqtt]), BACnet incl. experimental BACnet/SC ([bacnet]), OPC-UA ([opcua]). Read-only by construction; historian-first posture. Per-adapter flags documented in INGEST-PROTOCOLS.md.
  • Data quality — ingest.quality.assess (coverage, gaps, flatline, outliers, duplicate timestamps, composite score) and clean. Also reads two-regime structure (n_regimes / regime_threshold / regime_outlier_frac) so a duty-cycled point — a BTU meter, a lead pump, a status — is not scored as broken for cycling; a split is claimed only on mass and separation and temporal coherence, so a randomly-railed sensor is never mistaken for a schedule. Pooled outlier_frac keeps its meaning and is never masked. Flags: expected_freq, drop_outliers, regime_aware (off by default — sensorhealth opts in per role, since scoring a duty cycle as normal is the direction that could mask a fault).
  • Time / DST — timegrid: interval_hours, regularize (sort + de-duplicate the DST fall-back hour), localize (tz-localize resolving DST ambiguous/nonexistent), dst_anomalies. load_csv de-duplicates timestamps by default. See TIME-HANDLING.md.

Semantic model

  • Roles + mapping — model.roles.Role vocabulary; model.mapping.MappingProvider (alias + pattern → role). resolve.resolve(equip, roles) assembles a role-named frame. Flags: resample.
  • Entities + completeness — model.entities (Site/Equip/Point) with equipment-template completeness validation.
  • Brick interop — interop.mapping_from_brick / roles_from_brick (import); interop.to_brick and interop.site_to_ttl / site_from_ttl (export + whole-site round-trip). Flags: backend (auto/rdflib/minimal; rdflib via the [brick] extra).
  • Project-Haystack semantics — interop.haystack_tags / equip_haystack_tags (role→tags export) and, new in 0.6, interop.role_from_tags / roles_from_haystack / mapping_from_haystack (tag→role import) — closing the round-trip to Brick-level parity (all 54 roles recover).
  • ASHRAE 223P — interop.semantic223.site_to_223 / site_from_223 map a site (roles + equipment) to/from a 223P-shaped RDF subset (connections, medium, points; ROLE_TO_223 quantity-kinds, broadened in 0.6 to 44 of 54 roles — the full plant/DX/refrigerant side; status/command roles are documented as intentionally unmapped). Flags: profile (minimal/full), include_relations. See ONTOLOGY.md.

FDD — fault detection & diagnostics

Rule engine (rules.base.Registry, rules.builtin.builtin_registry); each rule consumes a role-frame and returns a Finding. Run with registry.run(name, equip_refs, mapping, min_trust=…).

  • Air-side (G36 + PNNL Re-tuning) — simultaneous heat/cool, reheat (penalty + G36 minimization), SAT reset, overcooling (min-flow + severity), economizer / OA-fraction (incl. under-ventilation), night/weekend setback, duct-static, zone census, and unmet-setpoint hours (unmet_setpoint_hours — occupied space temp outside the heating/cooling band, the operator-facing comfort/capacity metric). Per-rule flags (e.g. threshold, min_oa_pct, occupied_only, tol_F).
  • Central plant & hydronic — chiller kW/ton efficiency, chiller staging + multi-chiller fleet over-staging, cooling-tower approach, condenser-water reset, CHW/HW pump (riding-curve + VFD-min), CHW reset + low-ΔT, boiler summer-lockout + short-cycle. Flags include design targets (design_kw_per_ton, max_starts_per_day, …).
  • Control stability — control_hunting: flags a modulating output (valve/damper) that reverses direction excessively (unstable loop) by counting reversals/hour beyond a deadband. Flags: warn_per_hr, fault_per_hr, deadband. supply_air_control: flags supply-air temperature that fails to track its setpoint (control/capacity fault; running hours only). Flags: tol_F, warn_pct, fault_pct. airflow_tracking: flags measured VAV airflow that fails to track its setpoint (stuck/undersized damper, failed actuator, starvation, bad flow sensor). Flags: tol_frac, warn_pct, fault_pct.
  • Peer/cohort — cohort.CohortDeviation (fleet rule): flags a unit running unlike its peers on a role (robust z of a mean/peak/load-shape summary). Shipped instances cohort_airflow, cohort_space_temp; construct your own for any role. Flags: k, summary, min_cohort.
  • Economizer / free cooling — economizer_high_limit (OA damper open above the high limit — not locked out), free_cooling_missed (mechanical cooling ran while OAT was cool enough for free), static_pressure_reset (duct-static setpoint that doesn't trim with demand). Flags: high_limit_f, min_damper, min_range_inwc.
  • Packaged / DX & refrigerant-side (docs/FDD-DX.md) — compressor_short_cycle and compressor_staging (RTU/DX cycling + staging), heatpump_defrost (excess reversing-valve cycling), filter_fouling (filter ΔP at/above change-out), and chiller_approach_fouling (condenser/evaporator approach-temperature degradation — refrigerant-side fouling without refrigerant-pressure sensors). New equipment templates: RTU, HeatPump/VRF, DOAS, FCU.
  • Drift-detection families — catches equipment degrading over time against its own frozen, load-normalized baseline (the "is this slowly getting worse than it used to be, at matched load?" question), all on one shared engine (camber.chillerbaseline / camber.chillerdrift), each pairing a period statistic with a streaming sustained-shift CUSUM alarm and honest threshold labels (screening-grade magnitude floors vs. provisional-untuned CUSUM timing):
  • Chiller (CHILLER-DRIFT.md) — condenser/evaporator approach, liquid-line subcooling (charge), suction superheat (evaporator feed), condenser-water range.
  • Pump / hydronic (PUMP-DRIFT.md) — the distribution side at matched duty.
  • AHU / air-side (AHU-DRIFT.md) — supply fans, coils, filters, duct-static control, with a per-AHU co-movement roll-up (diagnose_ahu_drift) that names the locus.
  • VAV / zone-terminal (VAV-DRIFT.md) — the box's damper, airflow tracking, and reheat coil, with a per-box roll-up (diagnose_vav_drift) disambiguating box vs upstream starvation. Each family ships a physics simulator (ahusim / condensersim / evaporatorsim / vavsim) for ROC validation; camber.driftvalidation calibrates thresholds against labelled data. Period rules, run via Registry.run_periods with a frozen baseline store. Driven from a config's drift section or camber drift run|report|freeze|list (camber.driftrun) — one page per run via report.drift_report_html. Scoring is read-only toward the store; only freeze creates a reference and only the attributed accept_new_normal moves one, and an equipment nothing could evaluate is listed as not evaluated rather than diagnosed steady. See CLI.md.
  • Trim-and-Respond / G36 reset analytics (TR-RESET.md) — asks whether the plant's setpoint-reset logic does what ASHRAE Guideline 36 intends (camber.g36_reset engine). Five detectors: supply_air_reset_compliance (SAT held colder than the §5.16.2.2 OAT→SAT target — a reheat opportunity), sat/static_reset_effectiveness (does the reset setpoint actually trim and respond to its zone requests, or is it stuck / not-responding / not-trimming / diverging?), and sat/static_rogue_zone_census (fleet rules finding the one zone monopolizing the requests and dragging the whole reset). Screening / opportunity-grade.
  • G36 §5.16.14 engine — fdd_g36.run_g36_afdd scores AHU fault conditions FC1–FC15 with operating-state gating; cross-validated vs open-fdd and accuracy-scored in the synthetic harness (VALIDATION.md).
  • Sensor health / data trust — sensorhealth (physical bounds, cross-sensor consistency, per-role trust roll-up + trusted_roles gate), sensordrift (bias / drift / tracking vs a reference — fetch one with weather_source.oat_reference (NASA POWER by lat/lon), oat_reference_for (by address, via a keyless geocoder), or oat_reference_isd (station-precise, NOAA/ISD); see WEATHER.md), mapping_confidence. The runner's min_trust flag makes a rule decline when its inputs aren't trusted.
  • Prioritization & lifecycle — rules.triage: rank_findings (severity, or a magnitude/cost key), group_findings (root-cause grouping), FaultRegister (new/ongoing/resolved across runs). Persistent, cross-process: faultlifecycle.FaultLifecycle — a fingerprint-keyed fault store with an assignment/status workflow, SLA/aging tracking, and atomic JSON persistence. Flags: magnitude_key, actionable_only, reopen_on_recurrence, auto_resolve_absent.
  • Fault economics — fault_economics: per-fault annual $ impact → rank by money. Flags: params (assumptions), models, min_severity (via rank_by_cost). Triage-grade DEFAULT_MODELS cover simultaneous heat/cool, reheat, chiller/tower/pump efficiency, duct-static, boiler cycling, and the Trim-and-Respond reset family (SAT-below-target and static/SAT reset-not-trimming → reheat/fan waste; not_responding/stuck/diverges are comfort/indeterminate → uncosted by design). Drift findings are also uncosted by design — a drift is a leading recommission indicator, not a spend (its magnitude is a condition-space residual, not a priceable energy quantity). Every estimate carries its basis + assumptions and returns uncosted (never a fabricated figure) when the sizing it needs is missing.
  • Ventilation (ASHRAE 62.1) — ventilation.assess_62_1 (Ventilation Rate Procedure: required vs delivered OA, deficit) and assess_dcv (DCV modulation vs occupancy/CO₂), with the VentilationRateProcedure / DemandControlledVentilation rules and Role.OA_AIRFLOW. Flags: space_type vs rp/ra, ez, aggregate, min_corr, min_modulation. See VENTILATION.md.
  • Accuracy + CI gating — eval.benchmark + validation.metrics_with_ci (Wilson CIs), and eval.check_against_baseline to gate accuracy (TPR/FPR/diagnosis) against a committed baseline in CI (--json / --gate / --tol / --update-baseline). See VALIDATION.md.
  • Validation dossier — camber.dossier / camber validate aggregates all four validation tracks (synthetic, generated-fleet, real-data FDD, real-data M&V) into one text/HTML/JSON credibility artifact: live-recomputed pure tracks + cited real-data results with Wilson CIs and honest boundaries. See VALIDATION.md.

Sequence-of-Operations conformance

soo — a declarative clause engine (gated predicates over roles, JSON-authorable) measuring operated-vs-designed behavior as a conformance %, with soo_library (packaged ASHRAE G36 clauses). Flags: persistence window, per-class spec.

M&V — measurement & verification

See MANDV.md. Change-point models (mandv.models, 2P–5P + zero variants), LBNL TOWT (mandv.towt), fit statistics + G14 fractional savings uncertainty (mandv.stats), CUSUM (mandv.cusum), weather normalization (mandv.weather), normalized annual savings (mandv.normalized), non-routine adjustment (mandv.nonroutine), Option-B retrofit isolation (mandv.retrofit_isolation), CalTRACK alignment (mandv.caltrack), a variable-base degree-day baseline (mandv.degreeday, HDD/CDD regression with an auto-fit balance point), IPMVP Option A (mandv.option_a, measured Δparameter × stipulated duty), and IPMVP Option D (mandv.rc_model, a 1R1C or 2R2C grey-box calibrated to metered energy — grid-τ + OLS, G14-gated — run as-found vs as-corrected for a modeled pre-implementation saving, with multi-zone stacked-OLS calibration and an optional EnergyPlus cross-validator (interop.energyplus); see OPTION-D.md). CAMBER now covers IPMVP Options A/B/C/D. Flags: confidence, exclude_non_routine, model kinds, aggregate, balance_point, interval.

Streaming / online

Incremental monitors for a live BAS feed — bounded state, O(1)–O(window) per sample. See STREAMING.md and FORECAST.md.

  • Online M&V — mandv.online.OnlineCusum (incremental tabular CUSUM of savings/waste vs a baseline model → savings-erosion alarm) and RollingAnomaly (rolling median/MAD residual z-score). Flags: limit, slack, window, k, min_samples.
  • Online FDD — rules.online.OnlineFDD: sliding trailing-window rule evaluation emitting a Transition only on a verdict change (no per-sample re-alert), per-equipment isolation. Flags: window, eval_every, min_samples, emit_ok.
  • Forecasting + learned-normal anomalies — forecast.seasonal_forecast (time-of-week shape + additive drift, no ML dep), backtest (MAE / MAPE / CV(RMSE) honesty check), forecast_anomalies (robust residual band → FDD signal). Flags: drift_window, k, test_frac.

Commissioning (RCx / MBCx)

rcx: functional_test (FPT pass-rate), before_after (MBCx persistence across an intervention date), track_measures (measure register → verified/regressed/inconclusive/insufficient).

Money & compliance

  • Tariffs — tariff (URDB-shaped: TOU energy + tiers, TOU/flat demand, ratchet, fixed → monthly + annual bill), tariff.validate_bill (vs actual invoices, MAPE + per-month status), interop.openei (URDB fetch), [tariff] PySAM bridge. Flags: tol_pct.
  • ECM finance — finance: payback, NPV, IRR, SIR with escalation / O&M / salvage.
  • Demand & peak — demand: peak + drivers, load factor, baseload, night/weekend baseload anomaly, peak-shave $ value. Flags: near_peak_frac, start_hour/end_hour, target_kw.
  • BPS compliance — bps: site_eui, emissions_intensity, assess_bps / assess_eui (compliant?, margin, penalty exposure). Limits are caller-supplied (no hard-coded legal values).

Grid-interactive (GEB) & carbon timing

Beyond using less energy — quantify shifting and shedding load, and the carbon cost of when power is used. Advisory analytics (read-only toward the BAS). See GEB.md and CARBON.md.

  • Demand response & flexibility — geb.demand_response (shed kW/kWh/% + rebound vs a baseline), geb.flexibility (sheddable load above baseload, peak-to-average headroom). Flags: rebound_hours, baseload_pct.
  • Load timing — geb.carbon_aware_shift (CO₂ saved shifting load dirty→clean hours) and geb.operation_score (load timing vs a price/carbon signal, rearrangement-inequality bounds).
  • Hourly / marginal Scope-2 — carbon_hourly.hourly_emissions (time-varying factor → co2e, effective factor, timing premium) and marginal_vs_average (load-shift value uses marginal; reporting uses average). Flags: unit_kg_per_kwh.
  • OpenADR export — interop.openadr.to_openadr_report: map a demand_response result to an OpenADR-3.0-shaped report payload for a DR program.

Domain analytics

comfort (Std-55 PMV/PPD), iaq (CO₂ ventilation adequacy), cost, carbon, water (irrigation / cooling-tower / leak), loadprofile, pv (+ interop.pvlib_bridge, [pv]), interop.psychro (PsychroLib, [psychro]), lighting. Plus: - Schedule inference — schedule.detect_schedule / compare_schedule: the actual weekly operating schedule from interval load vs a stated one (setback opportunity). SCHEDULE.md. - Change-point detection — changedetect.detect_level_shifts: when a signal's mean shifts (MBCx persistence/regression). CHANGEDETECT.md. - Free-cooling opportunity — freecooling.free_cooling_opportunity: missed economizer hours → recoverable kWh/$. FREECOOLING.md. - Load disaggregation — disaggregate.disaggregate_load: baseload / weather / other split. DISAGGREGATE.md.

Advisory & synthesis

Read-only, human-in-the-loop layers on top of the findings: - ASO — aso.recommend / recommend_findings: an actionable finding → a suggested setpoint/ sequence change, grounded (cites the rule + G36/PNNL), never a BAS command. ASO.md. - Action plan — actionplan.build_action_plan: findings + fault_economics ($/yr) + aso, ranked worst-dollars-first; embeds in the audit report + config runs. ACTIONPLAN.md. - Health scorecard — scorecard.build_scorecard: per-category scores + an overall A–F grade. SCORECARD.md.

AI-assist (advisory, provider-agnostic)

Dependency-light, advisory-only, read-only toward the BAS. The LLM path is fully provider-agnostic — no vendor named, no SDK, no network (an AST guard enforces it) — and everything works with no LLM wired via deterministic fallbacks.

  • Assisted point mapping — mapping_assist.suggest_roles / review_unmapped: suggest roles for unmapped tags (a human-confirmed review list; never mutates a MappingProvider). FeatureSuggester (numpy baseline: string + unit + physical-range fit), optional MLSuggester ([ml] extra, scikit-learn, no pretrained weights), and LLMSuggester (agent seam; proposals validated + re-scored deterministically). See MAPPING-ASSIST.md.
  • Grounded explanation & Q&A — agent.explain / agent.ask: cited, plain-language explanations and NL Q&A over the findings/costs/recommendations/scorecard/completeness/history/mapping. A Context of citable Facts (order-stable ids), number-traceability verification (agent.check), a deterministic template fallback, and an injected complete(prompt, **opts) seam (client_from_callable). See AGENT.md.
  • Portfolio triage — agent.facts_from_fleet builds grounded facts from a report.FleetReport (per-building EUI / faults / recoverable $), and build_context(fleet=…) makes a multi-site context, so ask/explain answer portfolio-wide ("which building is worst?").

Storage

store.ParquetStore — entity-keyed, hive-partitioned (site/year) Parquet with tag-filtered reads, rollups, retention pruning, year-partition pruning + column projection + cached catalog. See SCALE.md. Flags: read_long(columns=…, start/end), rollup(freq, agg), prune(before_year).

Reporting, integration & API

  • Audit — report.AuditReport (ASHRAE/ACCA Standard 211, text/HTML) with prioritized findings.
  • Portfolio rollup — report.build_fleet_report (cross-sectional EUI benchmark + fault rollup, ranked by recoverable $). Flags: price, loads, peer_median_eui, top_n.
  • Outbound — integrate: CMMS work-orders (finding_to_ticket / findings_to_tickets → neutral dict), notifiers (dispatch_findings over webhook_transport / email_transport, with slack_payload / teams_payload formatters; severity filter + fingerprint dedupe), and findings/ metrics export (export_findings: CSV / Parquet / JSON). All opt-in, from the findings layer — never writing to the BAS. Flags: channel, min_severity, dedupe, dry_run, format, flatten_metrics. See INTEGRATIONS.md.
  • Charts + dashboard — the full visualization pattern catalog A–J: readiness ribbon (A), fault-annotated multi-trend (B), load carpet (E), data-quality dashboard (I), OAT cloud-shape scatter (D, oat_scatter), templated diagnostic scatters (G, diagnostic), rules as a chart engine (J, evidence — every rule renders its own proof), cohort small-multiples (C, cohort), M&V savings with uncertainty (H, savings), load profiles / load-duration curves (F, loadprofile_chart), plus the legacy scatters/CUSUM/energy-signature. report.build_dashboard assembles them into one self-contained HTML (matplotlib inlined, no web framework), embeds each finding's evidence (rules=), and offers a brush-able inline-SVG scatter (interactive=True). Flags: sections, rank_by, top_n, normalize, rules, evidence, interactive. See VISUALIZATION.md.
  • Read-only API + live web UI — api.server (camber serve <store> or python -m camber.api.server <store> [port]): GET /about /health /facilities /points /history, plus a live vanilla-JS dashboard at /ui (facility/equip/role selectors + a synchronized multitrend, brush-linked via window.CAMBER, polling for fresh data). Read-only, localhost-bound, CSP-locked, no framework. Env: CAMBER_STORE / CAMBER_API_HOST / CAMBER_API_PORT. See VISUALIZATION.md.

Orchestration & distribution

  • Config-driven runs — config: one JSON config (source → mapping → equipment → rules → report) runs a whole analysis: python -m camber.config run.json.
  • CLI — the camber console script: run / report / explain / ask / fleet / charts / validate / serve / drift / edge subcommands, with a vendor-neutral --llm-cmd seam for the agent. See CLI.md.
  • Plugins — plugins: third-party rules / ingest adapters / report formats discovered via Python entry points (camber.rules / camber.adapters / camber.reports) or registered in-process, duck-typed against the existing protocols with per-plugin error isolation. See PLUGINS.md.
  • Distribution & deployment — slim multi-stage Docker image + compose bundle (DOCKER.md), PyPI (camber-toolkit) + GHCR via the tag-driven release workflow, CI on 3.10/3.11, and reference Kubernetes / conda-recipe manifests (deploy/). See DEPLOY.md.

See also: ARCHITECTURE.md, ECOSYSTEM.md (fork-vs-depend analysis), and the ROADMAP.