Skip to content

Conversation

@gtfierro
Copy link
Member

@gtfierro gtfierro commented Sep 25, 2025

Replaces #721 . @fennibay @ektrah let me know what you think!

@gtfierro gtfierro marked this pull request as draft September 25, 2025 16:19
@github-actions
Copy link

The latest build of the Brick ontology on this PR is available here.

@github-actions
Copy link

The latest build of the Brick ontology on this PR is available here.

@fennibay
Copy link
Contributor

fennibay commented Oct 1, 2025

Thank you @gtfierro.

concerns and controls look good.

Now I see we missed one point about hosts. These hosted Collections need to contain not only Points and PointGroups, but also equipments. See #721: "A collection of entities can be hosted on a Controller (e.g. sensors, zones, light groups etc.), the hosts relationship from brick:Controller to brick:Collection would allow this. " #722 is also related to this.

Below some first ideas on how to address this, we shall discuss tomorrow:

  1. Extend PointGroup to also contain Equipment?
  2. Go back to Controller hosts Collection, no PointGroup?
  3. Merge this PR without hosts and look at it with Collections as part of other entities #722?
  4. Merge this PR AS IS, and look at the equipment in Collection with Collections as part of other entities #722?

Below another example assuming option 2 and #722 are in, just to give some concrete context.

@prefix bldg: <http://example.com/controller2#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix rec: <https://w3id.org/rec#> .
@prefix brick: <https://brickschema.org/schema/Brick#> .
@prefix bacnet: <http://data.ashrae.org/bacnet/2020#> .
@prefix unit: <http://qudt.org/vocab/unit/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix ref: <https://brickschema.org/schema/Brick/ref#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .

<http://example.com/controller2> a owl:Ontology ;
    owl:imports <https://brickschema.org/schema/1.4/Brick> .


bldg:Controller_1 a brick:Controller ;
    rdfs:label "AS20" ;
    brick:hosts bldg:HVAC1 ;
    brick:controls bldg:VavSu1 ;
    brick:concerns bldg:R009 ;
.

bldg:HVAC1 a brick:Collection ;
    brick:hasPart bldg:VavSu1 ;
    brick:hasPart bldg:HCl1 ;
.

bldg:VavSu1 a brick:Variable_Air_Volume_Box ;
    rdfs:label "VAV Supply Unit 1" ;
    brick:hasPart bldg:CdnMsgCol1 ;
.

bldg:CdnMsgCol1 a brick:Collection ;
    rdfs:label "Condensation Message Collection 1" ;
    brick:hasPart bldg:CdnMsgRs1 ;
.

bldg:HCl1 a brick:Heating_Coil ;
    rdfs:label "Heating Coil 1" ;
    brick:hasPoint bldg:Pos1 ;
.

bldg:CdnMsgRs1 a brick:Status ;
    rdfs:label "Condensation Message Result 1" ;
.

bldg:Pos1 a brick:Valve_PositionCommand ;
    rdfs:label "Heating Coil Position 1" ;
.

bldg:R009 a rec:Zone ;
    rdfs:label "Room 009 Zone" ;
    brick:hasPoint bldg:TR1 ;
    brick:hasPart bldg:SpTRDTr1 ;
.

bldg:TR1 a brick:Air_Temperature_Sensor ;
    rdfs:label "Room Temperature 1" ;
.

bldg:SpTRDTr1 a brick:Collection ;
    rdfs:label "Room Temperature Setpoint Determination 1" ;
    brick:hasPart bldg:SpTR1 ;
.

bldg:SpTR1 a brick:Air_Temperature_Setpoint ;
    rdfs:label "Room Temperature Setpoint 1" ;
.

@gtfierro gtfierro marked this pull request as ready for review October 30, 2025 15:05
@gtfierro
Copy link
Member Author

@fennibay @jbkoh @ektrah I wrote up some docs for the point group here: BrickSchema/docs#26 Please take a look and let me know what you think. Maybe we can merge this next week? I don't think there's any implementation left to do on the model

@gtfierro
Copy link
Member Author

I'm trying to merge this in, but I'm still not 100% happy with the "concerns" relationship name. How do you all feel about manages for the Controller/Zone relationship?

@fennibay
Copy link
Contributor

I'm trying to merge this in, but I'm still not 100% happy with the "concerns" relationship name. How do you all feel about manages for the Controller/Zone relationship?

manages sounds good to me.

@ektrah
Copy link
Contributor

ektrah commented Dec 11, 2025

I have two comments/proposals:

  • If I understand correctly, the SHACL constraint currently says:
    "If <some controller> controls <some equipment> and that equipment has <some point>, then the controller must also host <some point group> that includes that point."
    This seems to preclude nested point groups, such as:
    "The controller hosts <some point group> that includes <some other point group> that includes <some point>."
    I would propose to relax the SHACL constraint a bit to allow nested point groups.
  • Currently, a controller cannot host a point directly; the point must always be included in a point group.
    Conversely, a piece of equipment or a zone can only have points directly; the points of equipment and zones cannot be grouped.
    I would propose allowing controllers to host points directly (i.e., zero or more groups between controller and point instead of one or more) and allowing equipment and zones to have point groups (i.e., zero or more groups between equipment and point instead of zero).

Both are shown in this diagram using dotted lines.

brick-controls-hosts drawio

@github-actions
Copy link

The latest build of the Brick ontology on this PR is available here.

@github-actions
Copy link

The latest build of the Brick ontology on this PR is available here.

@github-actions
Copy link

The latest build of the Brick ontology on this PR is available here.

@github-actions
Copy link

The latest build of the Brick ontology on this PR is available here.

@gtfierro
Copy link
Member Author

@ektrah @jbkoh @fennibay let me know what you think!

@github-actions
Copy link

The latest build of the Brick ontology on this PR is available here.

@fennibay
Copy link
Contributor

@gtfierro thank you, it looks good. Matches what we discussed yesterday as the first step.

@github-actions
Copy link

The latest build of the Brick ontology on this PR is available here.

@gtfierro
Copy link
Member Author

One heads up; to get the tests to pass, I had to make brick:hasPart a subPropertyof rec:includes. Because Point Group is a rec:Collection, it needs at least 1 thing in the collection using rec:includes (this is the existing REC validation rule). By making hasPart a subproperty of includes, we get this automatically. @ektrah @jbkoh @fennibay this is what is necessary to use brick:hasPart instead of rec:includes

@github-actions
Copy link

The latest build of the Brick ontology on this PR is available here.

@github-actions
Copy link

The latest build of the Brick ontology on this PR is available here.

@jbkoh
Copy link
Contributor

jbkoh commented Dec 13, 2025

all look good to me, but I want to bring up another thing:
Shouldn't Sensor_Equipment be able to hostsPoint points as well?

@fennibay
Copy link
Contributor

Shouldn't Sensor_Equipment be able to hostsPoint points as well?

Do you see additional information that hasPoint wouldn't be able to express in this case?

Would we also need it for actuating equipment?

@jbkoh
Copy link
Contributor

jbkoh commented Dec 13, 2025

Yes, here is the query:
"I want to know for all points the locations of devices physically hosting them"

@jbkoh
Copy link
Contributor

jbkoh commented Dec 14, 2025

Let me expand the above comment a bit more. Originally, hasPoint was very loosely defined, and thus cover all the use cases alone. Now with the introduction of hostsPoint, we migrate a certain scope of hasPoint to hostsPoint as we discussed during the meeting. From BACnet perspective, we tend to think many things are Controllers, but there are many non-controller devices too. E.g., overlay sensors like occupancy sensors, which are not in BACnet but in buildings as a hardware device and sending data to a certain endpoint. An instance of Occupancy_Sensor isPointOf the sensor hardware, but at the same time it's also hostedPointBy the device too.

If we want hasPoint to represent such relation (physical hosting) for Sensor_Equipment, there are two issues

  • Meaning/scope of hasPoint varies in different context.
  • An actual query for the above case will be pretty confusing and should union different patterns based on types, something like
select ?point ?location {
  {
    ?equip brick:hostsPoint ?point.
    ?equip brick:hasLocation ?location.
    ?equip rdf:type brick:Controller.
  }
  UNION
  {
    ?equip brick:hasPoint ?point.
    ?equip brick:hasLocation ?location.
    ?equip rdf:type brick:Sensor_Equipment.
  }
}

Maybe our homework is to precisely define what "hosting" actually mean. To me, I define it as following

A physical device stores a Point and represents the Point's source.

Obviously, this definition is very rough, and there are many more cases to be considered.

  • Does a cloud server that is hosting all the copies of points hostsPoint the Points along with the source devices (e.g., a controller)? Are the copies of the Points considered different Points? Maybe, and that's why I was adding "represents the source" in my attempt of the definition.
  • If a Point originates from a certain device, but if the Point is only visible through a proxy, is the proxy hosting the Point or the origin device or both? Two representative examples are
    • A thermostat is not directly exposed through the network but only through a VAV controller. Are Points of the thermostat hosted by the thermostat or the vav controller?
    • Often, BMSes do not expose the field controllers but only as the BMS's own points. In that case, are the Points hosted by the BMS or the field controllers?

Another solution is to just loosen the shape and allow hostsPoint to be used by any Equipment.

It's still my desire to conclude this PR sooner than later, but I believe we need to set some direction on those topics before we conclude.

@fennibay
Copy link
Contributor

@jbkoh thanks for elaborating further.

  • Does a cloud server that is hosting all the copies of points hostsPoint the Points along with the source devices (e.g., a controller)? Are the copies of the Points considered different Points? Maybe, and that's why I was adding "represents the source" in my attempt of the definition.
  • If a Point originates from a certain device, but if the Point is only visible through a proxy, is the proxy hosting the Point or the origin device or both? Two representative examples are
    • A thermostat is not directly exposed through the network but only through a VAV controller. Are Points of the thermostat hosted by the thermostat or the vav controller?
    • Often, BMSes do not expose the field controllers but only as the BMS's own points. In that case, are the Points hosted by the BMS or the field controllers?

I think BMSs in general (including cloud) have quite some complexity. They have sometimes intermediaries/proxies to bring the point to their system, also there can be archiving systems (historians) and analytics systems that store copies of the points. Also, for BMS-local reasons, they might assign multiple IDs to the same point. I see the purpose of Brick+REC to make the automation system understandable. We don't need to understand how the BMS works. So I would leave all this out-of-scope.

I can support the thermostat example. For instance QAP22 cannot be accessed in the network, only via a Controller; but QMX6.P30 would be accessible if the client is connected to the network and speaks the KNX protocol, otherwise again accessed via controller.

Maybe our homework is to precisely define what "hosting" actually mean. To me, I define it as following

A physical device stores a Point and represents the Point's source.

You're absolutely right. I would remove the "stores" and "physical", because maybe it's not storing, but just making the Point accessible; and it might be a virtual device as well (like SW controller).

So my proposal would be: "Equipment hosts the Point, by making it available for access."

Options I see:

  • Option 1: Define hostsPoint it only for Controller.
    • Rationale: for sensors and actuators either it is not hosted at all, or hostsPoint will be for the same Equipment and Point like hasPoint. So we avoid unnecessary triples.
  • Option 2: Define hostsPoint for Equipment. All Equipments that make Points available for access could host it.
    • Rationale: make the hosting explicit for all types of Equipment.
  • Option 3: Do no define hostsPoint in Brick. This can be addressed via different means.
    • Rationale: keep it simple

In Option 1 and 3, we need an additional hint on how to access the point.

  • We use Web of Thing's hasInteractionAffordance to show the hosting relationship, which also allows us to define a Form for accessing it.
  • 223 uses hasExternalReference
  • Brick also allows BACnet-specific isObjectOf

The starting point for this (#721) was to host Collections as first step towards modelling Control Programs running on the Controller, hence we landed in Option 1. Now that it has evolved into hosting points, we could also wait for the eventual introduction of Functions.

@gtfierro
Copy link
Member Author

We still don't have a definition of "Controller" in the PR yet, so maybe this is the right opportunity to hash that out. Controller is a subclass of brick:ICT Equipment which is defined as

Information and Communications Technology (ICT) equipment operates with a processor to process data or logic and create digital signals.

Importantly, controllers can have a network address (rec:address). The hostsPoint relation means that the controller is responsible for exposing that Point to the rest of the network. In my mind, this makes hostsPoint meaningfully different from hasPoint. The latter associates the point with a equipment/space/loop. The former tells you where to find the point in the network.

I vote for Option 1, as it feels the cleanest and closest to the original intent of this development direction. Option 2 can get confusing with when to use hostsPoint vs hasPoint; I like the idea of keeping the controllers and equipment as separate concepts.

So, for @jbkoh's question:

"I want to know for all points the locations of devices physically hosting them"

the first part of his query should be sufficient (with one minor change)

select ?point ?location {
  {
    ?controller brick:hostsPoint ?point.
    ?controller brick:isPartOf?/brick:hasLocation ?location.
    ?controller rdf:type brick:Controller.
  }

The relationship between the Controller and Equipment must be present to find things this way. Here's what that sensor equipment might look like.

In the first case, the sensor equipment could have an integrated controller (I think hasPart is natural for this)

<temp1> a brick:Temperature_Sensor .

<sensor_hardware> a brick:Sensor_Equipment ;
	brick:hasPart <controller> .
	brick:hasPoint <temp1> .

<controller> a brick:Controller ;
	brick:controls <sensor_hardware> ;
	brick:hostsPoint <temp1> .

In the second case, the sensor has a connection to an external controller (perhaps through a wireless network)

<temp1> a brick:Temperature_Sensor .

<sensor_hardware> a brick:Sensor_Equipment ;
	brick:hasLocation <room1> .
	brick:hasPoint <temp1> .

<controller> a brick:Controller ;
	brick:controls <sensor_hardware> ;
	brick:hasLocation <IT_closet> . # different location than the sensor equipment
	brick:hostsPoint <temp1> .

@github-actions
Copy link

The latest build of the Brick ontology on this PR is available here.

@jbkoh
Copy link
Contributor

jbkoh commented Dec 15, 2025

The newly added definition reads pretty arbitrary:

An ICT device that exposes Points on a network and implements software to control or monitor equipment or systems using those Points.,

Do you have any reference on defining "Controller" as control or monitor?

The issue is not about when the Sensor Equipment and Controller (in the proposed definition) are separate, but when the Sensor Equipment is transmitting the data by itself. Sensor Equipment is a subclass of ICT Equipment, so it can certainly do it without a proxy, like many occupancy sensors do.

Why don't we change the range of hostsPoint to ICT_Equipment? Controller and Sensor_Equipment are siblings, and children of ICT_Equipment, and it logically makes sense for any ICT_Equipment to host Points.

@fennibay
Copy link
Contributor

I think hostsPoint on ICT_Equipment sounds good. It would also cover gateways etc.

@gtfierro
Copy link
Member Author

Just pushed the Controller -> ICT Equipment change for hostspoint/ishostedby. Do we want a similar change for the controls/isControlledBy relation?

@jbkoh I would love a better definition of controller! I just threw something in there

@github-actions
Copy link

The latest build of the Brick ontology on this PR is available here.

@jbkoh
Copy link
Contributor

jbkoh commented Dec 16, 2025

My reaction was towards monitor part, but as I read it again it monitors equipment/system, which might make sense. Still, starting only with controls but without monitor will be less controversial, and we can update the definition of controls as we discover more cases. Now I'm fine either.

RE: controls' domain, we'd want to be more specific about controls -- e.g., we don't want to say "A gateway (of VAV field controllers) controls VAVs". My initial thought goes to keeping the current controls shape.

@fennibay
Copy link
Contributor

I would also keep controls on the Controller.

Many thanks for driving this forward!

@github-actions
Copy link

The latest build of the Brick ontology on this PR is available here.

@github-actions
Copy link

The latest build of the Brick ontology on this PR is available here.

@gtfierro gtfierro merged commit dc05959 into master Dec 18, 2025
2 checks passed
@gtfierro gtfierro deleted the gtf-controller-model branch December 18, 2025 23:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants