Standard / BUS-1 v0.3 / Clause 9

9 Relationships§

AGREED The predicate set grew from 27 tokens in v0.1 to 44: 21 inverse pairs, symmetric connectedTo, and the deliberately weak references. v0.3 adds the submeter pair; earlier additions are listed in Decision Record group C.

9.1 Relationships are entities§

A relationship is an addressable entity with its own identifier, provenance, and validity period. It has a predicate, a subject, and an object, and MAY carry a medium, port qualifiers, and arbitrary qualifiers.

{ "id": "urn:uuid:...2014",
  "type": "bus:Relationship",
  "predicate": "bus:feeds",
  "subject": "urn:uuid:...051",         // AHU-1
  "object":  "urn:uuid:...052",         // VAV-2-01
  "medium": "air",
  "subjectPort": "supply", "objectPort": "inlet",
  "qualifiers": { "designFlow": { "value": 0.42, "unit": "m3/s" } } }

9.2 The normative predicate set§

An implementation MUST NOT use a bus:-prefixed predicate outside this set. The set, the meanings, and the cardinality hints below are one source, bus-predicates.json; this table renders from it, and the build fails if the registry and the schema enumeration disagree. Through v0.3 this table was typed by hand beside the enumeration — the arrangement whose failure mode the front matter of this document describes.

PredicateInverseCardinalityMeaning, subject to object
bus:containsbus:containedInmany-to-manySpatial or organizational containment. Transitive.
bus:hasPartbus:partOfone-to-manyCompositional part of an asset. Transitive. Equipment to component.
bus:hasMemberbus:memberOfmany-to-manyGrouping without containment. Not transitive. System to equipment, zone to space.
bus:locatedInbus:hasLocationmany-to-onePhysical placement of an asset in a space.
bus:servesbus:servedBymany-to-manyDelivery of a service to a space, zone, or asset.
bus:feedsbus:fedBymany-to-manyDirected flow of a medium. Requires medium.
bus:connectedTo(symmetric)many-to-manyUndirected physical connection, qualified by medium and port.
bus:powersbus:poweredBymany-to-manyElectrical supply. What an operator traces during an outage.
bus:measuresbus:measuredBymany-to-oneObservation. Point to the thing observed.
bus:commandsbus:commandedBymany-to-oneActuation by a point. Point to the thing acted upon.
bus:controlsbus:controlledBymany-to-manyGovernance by a controller, sequence, or strategy.
bus:hostsbus:hostedByone-to-manyProvision of an addressable home for a point. Device to point.
bus:appliesTobus:hasApplicablemany-to-manyAttachment of intent, an alarm definition, or a result to what it concerns.
bus:implementsbus:implementedBymany-to-manyA sequence or schedule realizes an intent.
bus:explainsbus:explainedBymany-to-manyKnowledge accounts for why something is as it is.
bus:supportsbus:supportedBymany-to-manyKnowledge or evidence supports an assertion.
bus:justifiesbus:justifiedBymany-to-manyA rationale justifies a decision or change.
bus:derivedFrombus:derivesmany-to-manyDependence of a calculated value on its inputs.
bus:documentedBybus:documentsmany-to-manyAttachment of a resource to what it describes.
bus:representsbus:representedBymany-to-oneA drawing or element depicts a building entity.
bus:replacesbus:replacedByone-to-oneLifecycle succession.
bus:hasSubMeterbus:subMeterOfone-to-manyMetering subdivision. The object meters a share of what the subject meters. New in v0.3; energy allocation was inexpressible without it.
bus:references(none)many-to-manyA link that is real but whose nature is not modeled. Deliberately weak.

The cardinality column is ADVISORY, and the grading is deliberate. It states the ordinary shape of the relationship, subject to object, so that a consumer building an index — a property graph, an object store, a triple store — knows what to expect and what to flag, instead of guessing and guessing differently from the next consumer. A package exceeding a hint is NOT invalid and MUST NOT be refused: dual electrical feeds through a transfer switch, a check meter observing two parents, and an asset consolidation replacing two things with one are all real, all legal, and all recorded as notes in the registry. The building is the authority on its own topology.

NOTE The inverse of a hint is its mirror — where bus:hosts is one-to-many, bus:hostedBy is many-to-one — and is derived from the registry, never stored in it.

Both directions of a pair are defined so an exporter can write whichever is natural. An implementation MUST NOT assert both directions of the same pair for the same subject and object; that is redundancy, and it diverges under editing. A receiving system MAY substitute the inverse on re-export, and test RT-3 accepts that.

9.3 Predicate semantics§

  • bus:feeds — MUST carry a medium. A flow relationship with no medium is not interpretable, and the medium is the property most often lost when a topology is flattened into a hierarchy.
  • bus:connectedTo — is symmetric and MUST NOT be asserted twice for the same pair. A duct has a direction and a pipe joint does not; one predicate cannot carry both, which is why there are two.
  • bus:measures and bus:commands — the subject MUST be a point. This is what separates a point from a value: a point is the thing that stands in a relationship to what it observes or acts upon.
  • bus:replaces — both endpoints MUST remain in the model. Replacement does not delete.

9.4 Ports§

PROVISIONAL New in v0.3. This closes the gap v0.2 called the largest remaining one in the information model. The shape is taken from ASHRAE 223P rather than invented, and the encoding is deliberately not Haystack’s.

Promotion criterion — an exporter from a system holding surveyed port structure round-trips ports, `pairedWith` and `mapsTo`; an exporter holding only topology omits ports and is accepted.

A port is a named place on an asset where a connection lands: the supply outlet of an air handler, the A side of a two-way valve, the return tapping of a coil. The asset declares its ports. The relationship names them.

Through v0.2 subjectPort and objectPort were free strings that referred to nothing. A receiver could read the word supply and could not check it, resolve it, or ask an asset what ports it has, so it was not possible to say which branch, which side of a valve, or that a coil has a supply and a return. That is the gap this clause closes.

9.4.1 A port is not an entity§

5.3.2 makes relationships entities because a relationship carries provenance and a validity period, can be asserted by one party and denied by another, and needs to be ended without deleting either endpoint. A port carries none of that. It has no identity apart from the asset that has it, no lifetime apart from that asset, and nothing to say that the asset does not already say. It is a name for a place, and a name for a place is intrinsic to the thing that has the place.

The cost of the alternative is concrete. Relationships are already roughly a third of package size (5.3.2). A port entity for every inlet and outlet would add one entity per opening on every pump, valve, coil, terminal unit and heat exchanger in a plant, for a fact the asset can carry in one array. Entity inflation is not a theoretical objection in a format an owner has to store, transfer and verify for decades.

NOTE The port declaration MAY carry its own provenance where the assertion needs attribution — a port structure surveyed in the field rather than taken from a submittal. That does not make a port addressable: nothing can reference one except by naming it on its asset.

9.4.2 What a port declares§

PropertyRequirement
nameREQUIRED. Unique among the ports of one asset, and case-sensitive. This is the string a relationship names.
directionREQUIRED. inlet, outlet, bidirectional, from the point of view of the asset that declares the port.
mediumREQUIRED. What moves through the port, from the same vocabulary a relationship uses (9.3).
labelRECOMMENDED. What the port is called on the drawing or the nameplate.
ordinalOPTIONAL. Distinguishes otherwise identical ports: a valve’s A and B sides, an air handler’s two return-air inlets.
pairedWithOPTIONAL. Names the port on the same asset carrying the other half of one circuit — a coil’s supply and its return.
mapsToOPTIONAL. Names an asset and a port on it that are the same physical opening as this one: an air handler’s supply outlet is really its supply fan’s outlet.
provenanceOPTIONAL. Clause 14.

Direction and medium are REQUIRED because a port that states neither is the free string again under another name. Direction is what makes a connection checkable — an outlet feeds an inlet — and medium is what makes it interpretable at all, for the same reason bus:feeds requires one.

"ports": [                                       // AHU-1
  { "name": "chwIn",   "direction": "inlet",  "medium": "chilledWater",
    "label": "CHW supply", "pairedWith": "chwOut" },
  { "name": "chwOut",  "direction": "outlet", "medium": "chilledWater",
    "label": "CHW return", "pairedWith": "chwIn" },
  { "name": "returnA", "direction": "inlet",  "medium": "air", "ordinal": 1 },
  { "name": "returnB", "direction": "inlet",  "medium": "air", "ordinal": 2 },
  { "name": "supply",  "direction": "outlet", "medium": "air",
    "mapsTo": { "assetRef": "urn:uuid:...058",   // the supply fan
                "port": "discharge" } } ]

ordinal is what Haystack’s encoding cannot express and what 9.4 was written to demand: two ports of the same medium and direction on one asset, told apart. pairedWith is what turns two openings into one circuit, so that a receiver knows a coil’s supply and return are the two ends of the same water path rather than two unrelated tappings. mapsTo is what keeps a containment hierarchy from lying: the air leaving an air handler leaves through the supply fan, and both statements are true at once.

9.4.3 Naming a port from a relationship§

NOTE An exporter that synthesizes port names or structure from a coarser topology assertion — expanding a source system’s single output-substance fact into a concrete supply port, say — produces a package indistinguishable from one that was surveyed. That synthesis is the 5.3.5 failure in its most durable form, and it is reported as a failure of EX-8. Omission remains declarable; invention is not.

The third of those is the one implementers will be tempted by, because a plausible port structure is easy to generate and looks like better data. It is not better data. A chiller given exactly one chilled-water outlet because the source said hasOutputSubstance may have four, and the receiver has no way to know that the number came from a guess.

9.4.4 Prior art, and what was declined§

  • ASHRAE 223P — the factoring is taken from s223:ConnectionPoint and its three subclasses, which give inlet, outlet and bidirectional, together with the two relations 9.4 needed most: s223:pairedConnectionPoint becomes pairedWith and s223:mapsTo becomes mapsTo. 223P is the only model in this field that has thought the problem through, and it is not credited anywhere in v0.2 because v0.2 had nothing to credit it for.
  • 223P’s Connection entity — declined. In 223P the duct, pipe or conductor is itself an entity with its own class, which is right for a physics-grade model and wrong here: it multiplies entity count across an entire hydronic plant to carry a fact that bus:feeds with a medium and two ports already carries. A duct MAY be a bus:Asset with assetKind: "component" where it matters. It is never required.
  • Brick 1.4.4 — has no port model at all. This was verified against the shipped ontology rather than assumed: there is no brick:hasPort, no brick:Port and no brick:Connection. brick:connectedTo exists as a bare symmetric predicate with no domain, no range, no direction and no medium, and the only Brick terms with Port in the name are 2 equipment classes. An import from a plain Brick model MUST leave ports absent (Annex G).
  • Project Haystack 4.0.0 — encodes a port as a supertype: 28 conjuncts of the form substance-input and substance-output, which 34 defs declare in their own is list. The input/output factoring is right and the encoding is why BUS did not follow it. Because the port is a supertype, an asset can declare at most one port per medium per direction, so a valve’s A and B sides on the same medium, an air handler’s second return-air inlet, and a coil’s supply and return are all inexpressible — which is exactly the list of things 9.4 exists to say. Declaring ports on the asset costs one array and says all three.

9.5 Extension predicates§

An implementation MAY define additional predicates in a declared namespace, and SHOULD do so rather than overloading bus:references. An importer MUST preserve relationships whose predicate it does not recognize.