Standard / BUS-1 v0.2 / Clause 7

7 Datatypes, properties, and semantics§

AGREED Property definitions (7.8) are new in v0.2 and are the change most likely to be felt by implementers.

7.1 Primitive types§

Five primitives: string, number, boolean, timestamp, and null. A binding MUST specify its numeric range and precision limits and MUST NOT silently narrow a value.

7.2 Text and language§

Any property typed Text accepts either a plain string or a language map keyed by [BCP47] tags. An importer supporting one language MUST preserve the full map and MUST NOT collapse it. Buildings outlive the tenancy that set their working language.

7.3 Timestamps§

A timestamp MUST be an [RFC3339] date-time with an explicit offset. A bare local time is not permitted anywhere in this standard.

An [RFC9557] IXDTF suffix MAY be appended to carry the originating time zone, and SHOULD be used where the civil time zone is operationally significant — schedule boundaries, occupancy transitions, event timestamps, and anything a human will later read as a wall-clock time. An importer MUST accept and preserve such a suffix even if it does not interpret it.

"assertedAt": "2019-04-11T14:00:00-05:00"
"at":         "2017-05-09T11:20:00-05:00[America/Chicago]"    (preferred for civil time)

NOTE Offset alone is not a time zone. A package recording only offsets loses the ability to reason about a daylight-saving transition that happened after export, which is exactly the reasoning an operator needs when reading a ten-year-old event log.

7.4 Quantities and unit codes§

A dimensional value MUST be expressed as a Quantity: a magnitude and a unitCode.

"grossArea":   { "value": 90000, "unitCode": "ft2" }
"designFlow":  { "value": 12500, "unitCode": "cfm" }
"lowLimit":    { "value": 50.0,  "unitCode": "degF" }
"filterAlarm": { "value": 1.0,   "unitCode": "inH2O" }

Unit codes are drawn from the vocabulary of Annex C. The codes are the ones an engineer writes on a drawing: degF, cfm, gpm, inH2O, kWh, tonRef. An operator reading a package should not have to consult an external registry to know what a value means, and should never meet an unfamiliar rendering of their own working units.

A unitSystem field MAY name a different vocabulary — ucum, haystack, bacnet, or qudt — for a unit Annex C does not cover. Absent the field, the vocabulary is bus. This is the same pattern the standard uses for classifications: define the small thing that is needed, and name the external vocabulary where one is used rather than forcing everything through it.

NOTE Temperature differences use the delta forms. A two degree rise is deltaDegF, not degF. Conflating the two is the most common unit error in building data and the model makes it expressible rather than relying on context.

7.5 Enumerations§

Where a point or property carries a discrete state, the enumeration MUST be declared rather than assumed from a protocol. Each member has a code, an OPTIONAL label, and an OPTIONAL isAlarm flag.

Enumerations defined by this standard are open. An importer encountering an unrecognized member MUST preserve the value and MUST NOT coerce it to a default (test IM-4). This is what allows the vocabulary to grow in a MINOR version without breaking deployed importers.

7.6 Digests§

A digest is written <algorithm>-<base64>. Only sha-256, sha-384, and sha-512 are defined, per [FIPS180-4], encoded per [RFC4648] section 4.

7.7 Classifications§

A classification records that an entity corresponds to a term in a taxonomy defined elsewhere: a system, an OPTIONAL version, a code, and an OPTIONAL label. An entity MAY carry any number, including several from the same system and several a receiving implementation considers inconsistent. This standard does not adjudicate between them.

NOTE The version field matters more than it appears to. A Brick 1.3 class URI and a Brick 1.5 class URI may be the same string with different meanings. Recording the version is what makes a mapping possible later; omitting it is what makes it guesswork.

7.8 Property definitions§

AGREED New in v0.2. Replaces the free-form property map of v0.1.

Every intrinsic fact about an entity that is not modeled by a named field is carried as a property value, and every property value references a bus:PropertyDefinition.

{ "type": "bus:PropertyDefinition",
  "propertyName": "filterClass",
  "datatype": "string",
  "meaning": "Particulate filtration efficiency rating of an air filter, stated in
              the rating scheme named by the value, for example a MERV rating
              under ASHRAE 52.2.",
  "origin": "manufacturer" }

"properties": [ { "definition": "urn:uuid:...076", "value": "MERV 13" } ]

The requirement exists because a free-form property map interacts badly with the completeness declaration, which is the honesty mechanism this standard leans on. An exporter could place most of what it knows in bare key-value pairs, declare the domain complete, and pass every other test — technically true, materially false.

The cost falls in the right place. A vendor with two hundred distinct property names writes two hundred definitions once per product and ships them with every export, whether the package covers fifty assets or fifty thousand. That is a one-time engineering cost on the vendor rather than a recurring interpretation cost on the owner.

7.8.1 Consequences§

  • Quantity kinds resolve here — a point’s quantityKind is a reference to a property definition rather than a free token (8.5). Point semantics and asset properties use one mechanism instead of two.
  • Package quality becomes measurable — the proportion of property values that are defined against those that are not is a figure an owner can read before purchase. It converts "is this export any good" from a judgment into a number.
  • Shared vocabulary grows bottom-up — definitions that many independent vendors emit identically are evidence of real shared meaning, and become promotion candidates into the core through the mechanism of 15.5. The standard never has to guess a taxonomy in advance.

Definitions are entities, so they carry provenance and revision. Who defined filterClass, when, and what changed when the definition was revised are all answerable.

A definition MUST NOT be silently merged with another of the same name but different meaning (test RT-21). Two vendors using capacity to mean different things is a fact about the world, and flattening it destroys the evidence that a human needs to reconcile them.