Prerequisite Please review the Learning Modules. This readme assumes that the audience is familiar with the high level concepts which comprise the building config.
In addition to a language and primitives for configuring an abstract building model, the Digital Buildings project provides a YAML configuration syntax for mapping concrete assets to the abstract model in a lightweight way. The intent of providing this syntax is to make "manual" onboarding faster and easier (because the resulting data file is machine readable and can be machine validated) as well as provide a clean interface format for machine-assisted onboarding to use.
NB: Some of the instructions here details that are specific to Google's implementation of this stack on its own campuses (such as references to CloudIoT registration). These should be relatively obvious to a critical reader, but if they are confusing feel free to post an issue in the project.
- For an explanation of types in the Digital Buildings abstract model see model
- For a conceptual explanation of the ontology see ontology
- Model Instance Configuration
Creation of a concrete model is primarily concerned with defining entities, their relationships to each other, and their relationships to real physical things in the world.
Conceptually, we divide entities into three categories:
- Logical Entity: An entity that maps 1:1 with a canonical concept in the model. For example, you might have an idealized concept of an Air Handler, with a corresponding entity type, that you may use for analysis. A logical air handler would use this type or a child of it.
- Reporting Entity: A reporting entity is one that generates telemetry data. Reporting entities are important to differentiate because they may have translations to convert their native data payload to a standard form.
- Virtual Entity A virtual entity does NOT directly generate telemetry data, but may still have a timeseries that is generated by linking data from other sources.
The following statements apply when considering entity categories:
- Either a Reporting Entity or a Virtual Entity may be a Logical Entity.
- Virtual Entities are typically also Logical Entities.
- By convention, anything that receives telemetry is a Reporting Entity, even if it has data linked from other entities. In practice, however, we do not recommend mixing the two concepts (i.e. by linking additional data from other devices into a reporting device).
To completely map real data to the model we also need a few more concepts:
- Translation: A key-value mapping between fields in a reporting device's payload and the standard fields in the device's assigned entity type.
- Link: A mapping between a standard field in one device and another standard field in another device. Links map data from reporting devices to virtual devices.
- Connection: Describes a relationship between two entities. See Connections
These should all be defined in a complete configuration.
While there is basically infinite diversity in what can be defined for a building, some elements are more or less expected in every model:
- All the logical spaces in the building with their unique names (Building, Rooms, Floors).
- Each logical piece of equipment (hereafter "device") and its associated Digital Buildings Type.
- Each reporting device registered in Cloud IoT (or your endpoint of choice, if not working on a Google building).
- Link mappings between the points of reporting devices and logical devices, if the two are not the same.
- Translation mappings between device-native point names and the standard point names for each reporting device
- Zones or Switch Groups, as applicable.
FEEDS
relationships between chained equipment in HVAC or power systems, as well as between terminal units and Zones.CONTROLS
relationships between switch groups and fixtures, and between switches and switch groups.CONTAINS
relationships between Zones or Switch Groups and rooms.CONTAINS
relationships between all entities and floors (or more specific space, if known).CONTAINS
relationships between Buildings and floors, and floors and rooms.
Each configuration file should contain the contents for one building (or other logical division of your universe). The reason for this is that the definitions in the file are intentionally not keyed by a globally unique identifier. This is done for a few of reasons:
- The human-readable entity code is, well, more human readable.
- Using human-readable codes, which are typically created at design time and known a-priori, allows for incremental population of the file at different stages of the commissioning or onboarding process, rather than having to wait until all the devices are cloud-registered.
- There is inherent value to forcing locally unique naming of spaces and equipment (because it makes it easier to find stuff).
The configuration format is focused around defining the entities in the model. A generic entity with all possible top level fields looks like this1:
NOTE: The new Building Config format switches entities being keyed by codes to being keyed by guids and Ids are removed. To convert the old format to the new format, run your config.yaml through the guid generator.
f7d82b75-ea41-49e2-bb5a-53228044eb4c # Entity keyed by a GUID
type: NAMESPACE/A_DIGITAL_BUILDINGS_ENTITY_TYPE
code: ENTITY-CODE
connections:
# Listed entities are sources on connections
ANOTHER-ENTITY-GUID: FEEDS
A-THIRD-ENTITY-GUID: CONTAINS
links:
A-FOURTH-ENTITY-GUID: # Source entity keyed by a GUID
# target_device_field: source_device_field
supply_air_damper_position_command: supply_air_damper_command_1
zone_air_temperature: zone_air_temperature_sensor_1
cloud_device_id: device-id-from-cloud-iot-registry
translation:
zone_air_temperature_sensor:
present_value: "points.temp_1.present_value"
units:
key: "pointset.points.temp_1.units"
values:
degrees_celsius: "degC"
supply_air_isolation_damper_command:
present_value: "points.damper_1.present_value"
states:
OPEN: "1"
CLOSED:
- "2"
- "3"
ENTITY-CODE:
guid: f7d82b75-ea41-49e2-bb5a-53228044eb4c # guid field is generated with guid generator.
type: NAMESPACE/A_DIGITAL_BUILDINGS_ENTITY_TYPE
connections:
# Listed entities are sources on connections
ANOTHER-ENTITY: FEEDS
A-THIRD-ENTITY: CONTAINS
links:
A-FOURTH-ENTITY: # Source entity code
# target_device_field: source_device_field
supply_air_damper_position_command: supply_air_damper_command_1
zone_air_temperature: zone_air_temperature_sensor_1
cloud_device_id: device-id-from-cloud-iot-registry
translation:
zone_air_temperature_sensor:
present_value: "points.temp_1.present_value"
units:
key: "pointset.points.temp_1.units"
values:
degrees_celsius: "degC"
supply_air_isolation_damper_command:
present_value: "points.damper_1.present_value"
states:
OPEN: "1"
CLOSED:
- "2"
- "3"
- GUID: A globally unique identifier for the entity. This field does not need to be included initially and can be generated with guid generator.
- Type: A valid, fully qualified Digital Buildings entity type that represents this entity.
- Code: The human readable identifier for the entity. This should be unique in document scope.
- cloud_device_id: the numeric device id from cloud iot registry. This field is mandatory when a translation exists. Must be a numeric string.
- Connections: Used to specify connections from other entities (sources) pointing to this entity, with connection types. Entities are keys and cannot be repeated. Values are one or more connections, specified as a single value or a set.
- Links: Used to specify mappings between standard fields of source
entities to standard fields of this entity. First level key is another
entity in the file (source). Second level key is a standard field of this
(target) entity followed by a
:
and a standard field of the other (source) entity. - Translation: Used to specify how the fields of the devices native payload map to the standard fields of this entity's type. See translation section for more detail.
The Digital Buildings platform has recently transitioned to the new format, which is identical to the above format except that entities were keyed by their codenand contained a separate id and guid field.
Entities are now keyed by a globally unique identifier and code has been moved to it's own separate field. id fields have been totally deprecated.
The old format is still valid if the id field is removed, and can be converted to the new format using the guid generator.
NOTE: Please continue using the old format, and use the guid generator to convert a building configuration to the new format.
In nearly every model, entities should exist for Buildings, Floors, and Rooms. The following example shows a building with one floor and one room:
# Building
A-BUILDING-CODE:
type: FACILITIES/BUILDING
# Floor
A-BUILDING-CODE-FLOOR1:
type: FACILITIES/FLOOR
connections:
A-BUILDING-CODE: CONTAINS
# Room
A-BUILDING-CODE-FLOOR1-ROOM123:
type: FACILITIES/ROOM
connections:
A-BUILDING-CODE-FLOOR1: CONTAINS
- Buildings shall have
CONTAINS
connections to Floors - Floors should have
CONTAINS
connections to all Rooms - Floors should have
CONTAINS
connections to all Devices
In this example, entities are identified by their globally unique identifiers. GUIDSs are widely used and highly recommended due to their exponentially low collision rate.
Types for spaces are contained in the FACILITIES
namespace of the ontology.
When sending data from a building via Cloud IoT, a reporting device is any device with its own entry in Cloud Device Manager (CDM)2.
For clarity the human readable ID of the device in CDM and the entity code in the config file should be the same3. If the building also has a CAD drawing or BIM model, good practice is for this code to also exist in the CAD or BIM model.
Choose an entity type that has the correct fields for this type.
Define a translation as necessary...
It is commonly (always?) the case that real devices have data payloads that differ from our modeled entity types. In this case, it is necessary to define a translation between the native payload and the standard form. This standardization includes the field names, field values, dimensional units and multistate definitions.
Below is a minimal example of what a translation configuration looks like in long form:
FCU-123:
...
translation:
zone_air_temperature_sensor:
present_value: "points.temp_1.present_value"
value_range: 15,25
units:
key: "pointset.points.temp_1.units"
values:
degrees_celsius: "degC"
supply_air_isolation_damper_command:
present_value: "points.damper_1.present_value"
states:
OPEN: "1"
CLOSED:
- "2"
- "3"
zone_air_temperature_setpoint: MISSING
Inside the translation
block, keys correspond to standard fields in the
ontology. Within each field block we provide information about the following:
present_value
: defines the fully qualified path in the device's native JSON payload that contains the value of this fieldvalue_range
: Ifpresent_value
is a dimensional number, defines the expected minimum and maximum value for the field, in the unit that is specified in theunits
block. This is an optional key and can be specified when there is a fixed range of values that the field is expected to have. If it is specified, then units must also be specified. The value range is used to measure data quality of telemetry and to validate writeback requests.units
: whenpresent_value
is a dimensional number, this block defines information about the payload location that defines dimensional units for this field'spresent_value
key
: defines the fully qualified path to the section of the payload that calls out the unitsvalues
: Maps a standard Digital Buildings unit to the value in the payload that represents that unit. Only one unit is allowed per field.
states
: Ifpresent_value
represents a multistate value, this block is used to map the native state values to standard ones. Each map key is a standard state, and its value is the corresponding native value, or a list of native values if more than one corresponds to the same standard state. It is important to point out that accepted state value(s) are of type string, integer, or boolean; however, internally these are all treated as, casted to, string(s).- If a device lacks a field required for its type, the field should be marked
MISSING
as shown above.
In order to eliminate duplicate work, the format provides some shortcuts to translation definitions:
- Substitute the
translation
block withtranslate_like:ENTITY-CODE
to use a translation that is already defined on another entity. The guid generator does this for you. - For devices that comply with UDMI a short form can be used.
In many cases the logical device and the reporting device are the same thing (i.e. the device that sends data is also the entity type you want in your model). When the two are different (i.e. the logical device does not send its own data) a virtual device is required.
Virtual entities are nearly always logical entities. Because logical entities are the representations that the applications using your model will care about, virtual devices should generally map to canonical types. In an integrated design in construction stack, logical devices should be called out by code in the CAD/BIM models and the same code should be used for them in this config.
A virtual entity example:
VAV-32:
type: NAMESPACE/DEVICE_TYPE
links:
ANOTHER-ENTITY: # source device
# target_device_field: source_device_field
supply_air_damper_position_command: supply_air_damper_command_1
...
The key difference between virtual and reporting entities is that all the fields
of a virtual entity are derived via links
. the link block lists all the source
entities and fields that contribute to this entity's data and provides a mapping
to this entity's local fields.
In addition to telemetry points, many devices will have relationships to other
entities. System and spatial relationships are defined with the connections
block. Connection definitions work the same way for all entities, with
connections always defined on the target of the connection.
Expanding the VAV definition from the previous section, and adding some lights:
VAV-32:
type: HVAC/VAV
connections:
A-BUILDING-FLOOR-GUID: CONTAINS
AN-AHU-GUID: FEEDS
LF-123:
type: LIGHTING/LIGHTING_FIXTURE
connections:
A-BUILDING-ROOM-GUID: CONTAINS
A-LIGHTING-GROUP-GUID: HAS_PART
In addition to spaces and devices, most buildings have other types of Logically
defined areas or groups that aren't strictly a "device". These entities are
simply virtual devices, following all the same rules, but often do not have
links
.
Here are some examples:
# HVAC Zone
ZONE-123:
type: HVAC/ZONE
connections:
A-BUILDING-FLOOR-GUID: CONTAINS
A-VAV-GUID: FEEDS
# Lighting Control Group
LCG-234:
type: LIGHTING/SWITCH_GROUP
connections:
A-BUILDING-ROOM-GUID: CONTAINS
A-SWITCH-GUID: CONTROLS
This document details the building configuration modes available in v1 Beta. The current version, v1 Alpha, is available with limited functionality.
- v1 Alpha:
- Interdependencies among entities are not allowed
- At most 2 different operations throughout all entities in the same building configuration; one of them being EXPORT.
- Instance Validator will reject a building config when more than 2 operations are specified building config and EXPORT is not present.
A building configuration file, with regard to data representation, can be grouped into two mutually exclusive parts:
-
A configuration metadata block that informs the program how to handle the entities contained in the building configuration.
-
Entity block(s) derived from a physical building; they model physical and virtual devices within a building. For more information please refer to the learning modules.
The configuration block, keyed by CONFIG_METADATA
, currently allows for
a single field operation
with values of INITIALIZE
or UPDATE
. This is
shown below for a general entity coded as E
and an UPDATE
configuration
operation.
CONFIG_METADATA:
operation: UPDATE
E-GUID:
type: ...
code: E
etag: ...
cloud_device_id: ...
translation: ...
connections: ...
links: ...
operation: [ ADD | DELETE | UPDATE | EXPORT ]
<update_mask: >
.
.
.
There is a specification for operation
in both the configuration metadata
block as well as the entity blocks contained within the building configuration
file. Although they share the same attribute name, their meanings differ. The
operation
contained within the CONFIG_METADATA block specifies the program
workflow for the building configuration file as a whole. Whereas the attribute
operation
of an entity details what is being done to that particular entity;
with an update_mask
(if applicable).
An additional attribute etag
has been included in each entity. The etag is
required for all entities under an UPDATE
configuration and used to sync
proposed changes with the current state (onboarded buildings). Under this
scenario, in addition to standard offline validation checks, etags are compared
between the building configuration file and backend datastore. Successfully
validating the proposed update if all etags align; signaling that the update
building configuration is synced to the current state. The etags are generated
upon export and are not created by user; i.e. updates can only be applied to
a previously exported building configuration.
In the context of a building configuration file, the program is agnostic to the location of the configuration metadata block. However, the standard practice is to place this at the very top of the building configuration.
CONFIG_METADATA:
operation: INITIALIZE
E1-GUID:
type: ...
code: E1
...
E2-GUID:
type: ...
code: E2
...
E3-GUID:
type: ...
code: E3
...
Default operation for modeling a building yet to be onboarded. In this
mode of operation the program will treat the entire contents of the building
configuration as a new instantiation. The operation
attribute for each entity
contained within the building config will default to ADD
; unless otherwise
specified. Allowed entity operation values in this mode are of ADD
or EXPORT
and is enforced by the instance validator. The building config must pass all
standard offline validation checks. If the CONFIG_METADATA
block is missing
from the building configuration the program will assume this mode of operation.
An INITIALIZE
configuration only allows EXPORT
operations on previously
onboarded entities. This is shown below with specified operations for entities
E1, E2, and an export of building entity E3; note that there is no specification
of operation for entity E2.
CONFIG_METADATA:
operation: INITIALIZE
E1-GUID:
type: ...
code: E1
operation: ADD
...
E2-GUID: # no operation specified, ADD assumed
type: ...
code: E2
connections:
E3-GUID: CONNECTS_TO # reference connection to an onboarded building
...
E3-GUID: # export an onboarded building as its referenced by E2
type: FACILITIES/BUILDING
code: E3
operation: EXPORT
...
In this mode the configuration will be considered as a scoped view of an already
instantiated building; allowing users to perform operations of ADD
,
DELETE
, UPDATE
, and EXPORT
on entities. This follows the copy-and-replace
strategy:
- Missing parts from the block will be removed.
- New parts in the block will be added.
- Existing parts in the block will be updated.
Under the UPDATE
configuration:
-
Any entity without a specification for operation or update_mask will default to
EXPORT
. Therefore the following two entities are equivalentE-GUID: # This definition for E is equivalent to the one below type: ... code: E operation: EXPORT ... E-GUID: type: ... code: E ...
-
The
EXPORT
operation:- Results in no change to the instantiated entity; i.e. no-op
- Must be used to include entities which are referenced by others undergoing update
E2-GUID: # E0-GUID is updating its source to E2-GUID, it must be included type: ... code: E2 E0-GUID: type: ... code: E3 operation: UPDATE update_mask: - connections connections: E2-GUID: CONNECTS_TO ...
-
If the update_mask is specified, the operation for that entity is assumed
UPDATE
.E-GUID: # These two entity definitions for E are equivalent type: ... code: E operation: UPDATE update_mask: - ... ... E-GUID: type: ... code: E update_mask: - ... ...
This mode, with an entity operation of UPDATE
, introduces another attribute
to the entity blocks keyed by update_mask
. This is shown in the example for
an entity coded as E4, showing all possible entity attributes, where
update_mask
is given with fields of translation
and cloud_device_id
.
Note that etag
is required for UPDATE
and DELETE
but not for ADD
operations.
CONFIG_METADATA:
operation: UPDATE
E4-GUID:
type: ...
code: E4
etag: ...
cloud_device_id: ...
translation: ...
connections: ...
links: ...
operation: UPDATE # This can be omitted when update_mask is specified
update_mask:
- translation
- cloud_device_id
There are various types of updates that can be performed. All of these updates
are performed according to the fields provided in the update_mask
. They are
grouped in the following categories:
This update typically occurs alongside an update to the translation
or links
. If the update to another type contains the same fields, as the previous type,
this can be done independently. The entity type can be changed to any valid
identifier but cannot be cleared. This is shown in the description for Code update.
This update may be completed independently; however, it typically follows a type
update. In the following example: the code is updated from FAN-123
to
PMP-123
which follows a change of type from HVAC/FAN_SS to HVAC/PMP_SS. Since
the two types share the same fields there is no need to make updates to the
translations.
-
Instantiated Entity:
GUID-123: type: HVAC/FAN_SS code: FAN-123 ...
-
Update:
GUID-123: type: HVAC/PMP_SS code: PMP-123 ... update_mask: - type - code
In general, a type update requires an update of the translation. These updates
are completed on the standard field by the following: replacement and mapping,
addition, or removal. For example an entity coded as ENTITY-CODE
with
the required fields field_a
, field_b
, and field_c
:
ENTITY-GUID:
type: SOME_TYPE_NAMESPACE/SOME_TYPE_A
code: ENTITY-CODE
etag: ...
cloud_device_id: NEW-CLOUD-DEVICE-ID
translation:
field_a:
present_value: points.analog-value_1.present_value
units: ...
field_b:
present_value: points.analog-value_2.present_value
units: ...
field_c:
present_value: points.analog-value_3.present_value
units: ...
To change the type from SOME_TYPE_A to SOME_TYPE_B in the same namespace
requiring fields: field_b
, field_c
, and field_d
. This can be done as
follows:
ENTITY-GUID:
type: SOME_TYPE_NAMESPACE/SOME_TYPE_B
code: ...
etag: ...
cloud_device_id: ...
translation:
field_b:
present_value: points.analog-value_2.present_value
units: ...
field_c:
present_value: points.analog-value_3.present_value
units: ...
field_d:
present_value: points.analog-value_4.present_value
units: ...
update_mask:
- type
- translation
Note: a type update typically requires a code update. This has been omitted from the example for brevity. Any field that is omitted is deleted, not present in the instantiated entity is added, or present is ignored.
The value ranges for particular fields on an entity can be updated as part of the translation:
ENTITY-GUID:
type: SOME_TYPE_NAMESPACE/SOME_TYPE_A
code: ENTITY-CODE
etag: ...
cloud_device_id: NEW-CLOUD-DEVICE-ID
translation:
field_a:
present_value: points.analog-value_1.present_value
value_range: 4.5,90.0
units: ...
field_b:
present_value: points.analog-value_2.present_value
units: ...
field_c:
present_value: points.analog-value_3.present_value
value_range: 15,25
units: ...
update_mask:
- value_range
- translation
Since the value range is not actually part of a device translation, it must be listed separately in the update mask. Whenever a value range is specified, it overrides any previously specified value range and can only be overridden by a new value range in a new building config.
The entity's connections can be updated to reflect a new connection type,
source, or can be cleared. An update to both the source entity and connection
type together is allowed. For example: an entity coded as LF-123
with a
connection to source entity coded as LCG-123
:
LF-123-GUID
type: LIGHTING/LIGHTING_FIXTURE
code: LF-123
etag: ...
cloud_device_id: ...
connections:
LCG-123-GUID: HAS_PART
The connection type can be updated from HAS_PART
to CONNECTS_TO
as:
LF-123-GUID
type: LIGHTING/LIGHTING_FIXTURE
code: LF-123
etag: ...
cloud_device_id: ...
connections:
LCG-123-GUID: CONNECTS_TO
update_mask:
- connections
The connection source can be updated from LCG-123-GUID
to LCG-234-GUID
as:
LF-123-GUID
type: LIGHTING/LIGHTING_FIXTURE
code: LF-123
etag: ...
cloud_device_id: ...
connections:
LCG-234-GUID: HAS_PART
update_mask:
- connections
Or all connection can be cleared by specifying connections in the update_mask and no specification for connections:
LF-123-GUID
type: LIGHTING/LIGHTING_FIXTURE
code: LF-123
etag: ...
cloud_device_id: ...
update_mask:
- connections
The links exist on virtual entities and are tied to physical entities and more
precisely to the standard fields of a given translation Virtual Devices.
Therefore, when an entity type is updated with a change applied at the
translation level, the links must be updated. The links update follows the same
concept as the translation depicted earlier. For example: a virtual entity coded
as VIRTUAL-ENTITY-123
of TYPE-C
is linked to another coded as ENTITY-123
with
type TYPE-A
and fields: field_a
, field_b
, field_c
.
ENTITY-A-123-GUID:
type: SOME_TYPE_NAMESPACE/TYPE-A
code: ENTITY-A-123
etag: ...
cloud_device_id: ...
translation:
field_a:
present_value: points.analog-value_1.present_value
units: ...
field_b:
present_value: points.analog-value_2.present_value
units: ...
field_c:
present_value: points.analog-value_3.present_value
units: ...
VIRTUAL-ENTITY-C-123-GUID:
type: SOME_TYPE_NAMESPACE/TYPE-C
code: VIRTUAL-ENTITY-C-123
etag: ...
cloud_device_id: ...
links:
entity-123:
field_a: field_a_1
field_b: field_b_1
field_c: field_c_1
It is required to change the type of ENTITY-123 from TYPE-A to TYPE-B with fields: field_b, field_c, and field_d; necessitating an update also to its code and links. In addition VIRTUAL-ENTITY-123, which depends on ENTITY-123, must be updated. This can be achieved by the following:
ENTITY-A-123-GUID:
type: SOME_TYPE_NAMESPACE/TYPE-B
code: ENTITY-B-123
etag: ...
cloud_device_id: ...
translation:
field_b:
present_value: points.analog-value_1.present_value
units: ...
field_c:
present_value: points.analog-value_2.present_value
units: ...
field_d:
present_value: points.analog-value_3.present_value
units: ...
update_mask:
- type
- code
- translation
VIRTUAL-ENTITY-C-123-GUID:
type: SOME_TYPE_NAMESPACE/TYPE-D
code: VIRTUAL-ENTITY-D-123
links:
ENTITY-A-123-GUID:
field_b: field_b_1
field_c: field_c_1
field_d: field_d_1
update_mask:
- type
- links
The building config can be machine validated for consistency and adherence to the rules defined in the data model. This tool is available here.
Footnotes
-
A user would almost never define all the sections in a single entity, but all are shown below for illustration purposes. \ ↩
-
Practically speaking, the entry typically corresponds to the controller, which may or may not map to exactly one complete piece of equipment. \ ↩
-
An unstated assumption here is that the CDM registry scope and the scope of the config file are the same. This guarantees that a unique ID can be found in the CDM registry for each entity. ↩