Data model
Rules are driven by the model in NF. Open-FDD finds sites, equipment and points from NF’s Haystack tags. It has no site-specific code or settings: tag the model in NF, then reload the app.
| Record | Fields Open-FDD uses |
|---|---|
| Site | latitude, longitude, timezone, optional area and areaUnit |
| Equipment | siteRef, equipment markers such as ahu, vav, chiller |
| Point | siteRef, equipRef, class, markers, kind, unit, history |
Trend every point a chart or rule uses. Site coordinates feed the weather hook; floor area feeds energy-intensity charts.
Roles bind points to rule inputs
A rule asks for named roles, for example supply-air temperature or fan command. A point fills a role when its NF class matches one of the role’s classes, or when it carries every marker of the role. Class wins because it is more specific.
- Markers are one comma-separated string in NF. Setting a class does not add markers.
- Equipment kinds come from the equipment markers. Weather points fill weather roles only.
- The role-to-class and marker map is
nf-app/static/fdd-catalog.json. The rule catalog and cookbooks list each rule’s roles. - The FDD and RCx pages show missing required roles. Fix the class or markers in NF, check the point has history and a unit, reload.
Units are SI-first
The engineer declares each point’s unit in NF. Ingest converts supported units to SI; rules and stored results stay SI. Imperial is display-only. Unknown or incompatible units are skipped, never guessed from the value: a unitless 0.5 could be a fraction or a percent.
| Quantity | SI unit |
|---|---|
| Temperature / difference | °C / Δ°C |
| Pressure | Pa |
| Flow | L/s |
| Power / energy | kW / kWh |
| Relative humidity | %RH, 0-100 |
| Commands, positions | fraction, 0-1 |
| Status | 0/1 |
Accepted input units, imperial display and per-rule units are in the units convention. The
conversion table is open_fdd/data/units.json, shared by the browser (nf-app/static/units.js) and Python (open_fdd/nf/units.py).
Sensor-validation rules also require the sensor’s declared unit to match its SI quantity.
RDF and SPARQL
The Model and RDF tab exports the Haystack model as Turtle with stable subjects. References resolve within their site and each point links to its NF time-series id. The tab flags dangling references and non-standard tags.
| Use | How |
|---|---|
| Check a Turtle file | pip install rdflib pyoxigraph, then python tools/rdf-check/check_ttl.py model.ttl |
| Build Turtle from a fixture | node tools/rdf-check/gen_ttl.js fixture.json fixture.ttl (fixture has a records array) |
| Query in the browser | SELECT, ASK, CONSTRUCT or DESCRIBE over the loaded model; results are capped and download as CSV |
| Query from code (Full) | POST /api/v1/apps/{app-id}/hooks/sparql, then read GET /api/v1/apps/{app-id}/hooks/sparql/runs?include_results=true |
Updates and remote SERVICE queries are refused. Request and response shapes are in the API reference.