From f697d88bae7b17e69de78bfa524e8d216ffe6261 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Do=C4=9Fan=20Fennibay?= Date: Fri, 29 Aug 2025 08:39:20 +0200 Subject: [PATCH 01/15] feat: introduce special relationships for Controller: controls, concerns and hosts Also symmetric relationships are added --- bricksrc/relationships.py | 48 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/bricksrc/relationships.py b/bricksrc/relationships.py index ce55fb28..8ca8e9c2 100644 --- a/bricksrc/relationships.py +++ b/bricksrc/relationships.py @@ -162,6 +162,48 @@ "domain": BRICK.Point, RDFS.label: Literal("Has unit", lang="en"), }, + "controls": { + A: [OWL.ObjectProperty, OWL.AsymmetricProperty, OWL.IrreflexiveProperty], + OWL.inverseOf: BRICK["isControlledBy"], + "range": BRICK.Equipment, + "domain": BRICK.Controller, + RDFS.label: Literal("Controls", lang="en"), + }, + "isControlledBy": { + A: [OWL.ObjectProperty, OWL.AsymmetricProperty, OWL.IrreflexiveProperty], + OWL.inverseOf: BRICK["controls"], + "range": BRICK.Controller, + "domain": BRICK.Equipment, + RDFS.label: Literal("Is controlled by", lang="en"), + }, + "hosts": { + A: [OWL.ObjectProperty, OWL.AsymmetricProperty, OWL.IrreflexiveProperty], + OWL.inverseOf: BRICK["isHostedBy"], + "range": REC.Collection, + "domain": BRICK.Controller, + RDFS.label: Literal("Hosts", lang="en"), + }, + "isHostedBy": { + A: [OWL.ObjectProperty, OWL.AsymmetricProperty, OWL.IrreflexiveProperty], + OWL.inverseOf: BRICK["hosts"], + "range": BRICK.Controller, + "domain": REC.Collection, + RDFS.label: Literal("Is hosted by", lang="en"), + }, + "concerns": { + A: [OWL.ObjectProperty, OWL.AsymmetricProperty, OWL.IrreflexiveProperty], + OWL.inverseOf: BRICK["isConcernedBy"], + "range": REC.Zone, + "domain": BRICK.Controller, + RDFS.label: Literal("Concerns", lang="en"), + }, + "isConcernedBy": { + A: [OWL.ObjectProperty, OWL.AsymmetricProperty, OWL.IrreflexiveProperty], + OWL.inverseOf: BRICK["concerns"], + "range": BRICK.Controller, + "domain": REC.Zone, + RDFS.label: Literal("Is concerned by", lang="en"), + }, "meters": { A: [OWL.ObjectProperty, OWL.AsymmetricProperty, OWL.IrreflexiveProperty], OWL.inverseOf: BRICK.isMeteredBy, @@ -238,4 +280,8 @@ if row["datatype"]: relationships[row["path"]][A] = [OWL.DatatypeProperty] if row["nodeKind"]: - relationships[row["path"]][A] = [OWL.ObjectProperty, OWL.AsymmetricProperty, OWL.IrreflexiveProperty] + relationships[row["path"]][A] = [ + OWL.ObjectProperty, + OWL.AsymmetricProperty, + OWL.IrreflexiveProperty, + ] From 1c8a1391368ece23f2673f159e3633662f1c633d Mon Sep 17 00:00:00 2001 From: Gabe Fierro Date: Thu, 25 Sep 2025 10:18:34 -0600 Subject: [PATCH 02/15] working on poitn group + controller model --- bricksrc/collections.py | 6 ++++- bricksrc/equipment.py | 1 + bricksrc/relationships.py | 4 +-- bricksrc/rules.ttl | 20 +++++++++++++++ examples/controller/controller.ttl | 40 ++++++++++++++++++++++++++++++ 5 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 examples/controller/controller.ttl diff --git a/bricksrc/collections.py b/bricksrc/collections.py index 2da6e474..da5f7f93 100644 --- a/bricksrc/collections.py +++ b/bricksrc/collections.py @@ -1,4 +1,4 @@ -from .namespaces import TAG, OWL, BRICK +from .namespaces import TAG, REC, BRICK system_subclasses = { "Automatic_Tint_Window_Array": { @@ -159,6 +159,10 @@ "tags": [TAG.Collection, TAG.Portfolio], "constraints": {BRICK.hasPart: [BRICK.Site]}, }, + "Point_Group": { + "tags": [TAG.Collection, TAG.Point_Group], + "constraints": {REC.includes: [BRICK.Point]}, + }, "System": { "tags": [TAG.Collection, TAG.System], "subclasses": system_subclasses, diff --git a/bricksrc/equipment.py b/bricksrc/equipment.py index 972de102..49a3729c 100644 --- a/bricksrc/equipment.py +++ b/bricksrc/equipment.py @@ -57,6 +57,7 @@ }, "Controller": { "tags": [TAG.Equipment, TAG.ICT, TAG.Controller], + BRICK.hosts: [BRICK.Point_Group], "subclasses": { "BACnet_Controller": { "tags": [TAG.Equipment, TAG.BACnet, TAG.Controller], diff --git a/bricksrc/relationships.py b/bricksrc/relationships.py index 5f8de352..59212371 100644 --- a/bricksrc/relationships.py +++ b/bricksrc/relationships.py @@ -179,7 +179,7 @@ "hosts": { A: [OWL.ObjectProperty, OWL.AsymmetricProperty, OWL.IrreflexiveProperty], OWL.inverseOf: BRICK["isHostedBy"], - "range": REC.Collection, + "range": BRICK.Point_Group, "domain": BRICK.Controller, RDFS.label: Literal("Hosts", lang="en"), }, @@ -187,7 +187,7 @@ A: [OWL.ObjectProperty, OWL.AsymmetricProperty, OWL.IrreflexiveProperty], OWL.inverseOf: BRICK["hosts"], "range": BRICK.Controller, - "domain": REC.Collection, + "domain": BRICK.Point_Group, RDFS.label: Literal("Is hosted by", lang="en"), }, "concerns": { diff --git a/bricksrc/rules.ttl b/bricksrc/rules.ttl index 8ccbcd3e..bdb493e3 100644 --- a/bricksrc/rules.ttl +++ b/bricksrc/rules.ttl @@ -556,3 +556,23 @@ bsh:InheritEVSEChargerDirection a sh:NodeShape ; """ ; ] ; . + +# check that controllers host the points of the equipment they control +bsh:CheckControllerHostsPointGroups a sh:NodeShape ; + sh:targetClass brick:Controller ; + sh:sparql [ + a sh:SPARQLConstraint ; + sh:message "Controllers should host the points of the equipment they control" ; + sh:prefixes ; + sh:select """ + SELECT $this ?pt ?eq WHERE { + $this brick:controls ?eq . + ?eq brick:hasPoint ?pt . + FILTER NOT EXISTS { + $this brick:hosts ?pg . + ?pg rec:includes ?pt . + } + } + """ ; + ] +. diff --git a/examples/controller/controller.ttl b/examples/controller/controller.ttl new file mode 100644 index 00000000..b100858e --- /dev/null +++ b/examples/controller/controller.ttl @@ -0,0 +1,40 @@ +@prefix bldg: . +@prefix rdfs: . +@prefix rec: . +@prefix brick: . +@prefix bacnet: . +@prefix unit: . +@prefix xsd: . +@prefix ref: . +@prefix owl: . + + a owl:Ontology ; + owl:imports . + + +bldg:Controller_1 a brick:Controller ; + rdfs:label "Main Building Controller" ; + brick:hosts bldg:VAV1PointGroup ; + brick:controls bldg:VAV1 ; +. + +bldg:VAV1PointGroup a brick:Point_Group ; + rdfs:label "VAV1 Point Group" ; + rec:includes bldg:VAV1_Temperature_Sensor, bldg:VAV1_Occupancy_Sensor ; +. + +bldg:VAV1_Temperature_Sensor a brick:Temperature_Sensor ; + rdfs:label "VAV1 Temperature Sensor" . + +bldg:VAV1_Occupancy_Sensor a brick:Occupancy_Sensor ; + rdfs:label "VAV1 Occupancy Sensor" . + +bldg:VAV1 a brick:Variable_Air_Volume_Box ; + rdfs:label "VAV1" ; + brick:hasPoint bldg:VAV1_Temperature_Sensor, bldg:VAV1_Occupancy_Sensor ; + brick:feeds bldg:Zone1 ; +. + +bldg:Zone1 a rec:HVACZone ; + rdfs:label "Zone 1" ; +. From 9557c79dc159bff320b0bb3ffb0bee0a33a2422e Mon Sep 17 00:00:00 2001 From: Gabe Fierro Date: Thu, 25 Sep 2025 11:03:52 -0600 Subject: [PATCH 03/15] fixing implementation --- bricksrc/collections.py | 2 +- bricksrc/recpatches.ttl | 6 +----- examples/controller/controller.ttl | 1 + 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/bricksrc/collections.py b/bricksrc/collections.py index da5f7f93..241cab88 100644 --- a/bricksrc/collections.py +++ b/bricksrc/collections.py @@ -161,7 +161,7 @@ }, "Point_Group": { "tags": [TAG.Collection, TAG.Point_Group], - "constraints": {REC.includes: [BRICK.Point]}, + "constraints": {REC.includes: [BRICK.Point, BRICK.Point_Group]}, }, "System": { "tags": [TAG.Collection, TAG.System], diff --git a/bricksrc/recpatches.ttl b/bricksrc/recpatches.ttl index 5cd5cc2c..623f0b14 100644 --- a/bricksrc/recpatches.ttl +++ b/bricksrc/recpatches.ttl @@ -1180,10 +1180,6 @@ brick:Collection sh:property [ rdf:type sh:PropertyShape ; sh:path rec:includes ; - sh:or ( - [ sh:class brick:Equipment ] - [ sh:class brick:Collection ] - ) ; sh:minCount 1 ; sh:name "includes" ; sh:nodeKind sh:IRI ; @@ -1833,4 +1829,4 @@ rec:AudioVisualEquipment brick:deprecatedInVersion "1.4.0" ; brick:deprecationMitigationMessage "REC ICT classes are being phased out in favor of Brick classes. For a replacement, consider brick:Audio_Visual_Equipment" ; brick:isReplacedBy brick:Audio_Visual_Equipment ; -. \ No newline at end of file +. diff --git a/examples/controller/controller.ttl b/examples/controller/controller.ttl index b100858e..bc95104d 100644 --- a/examples/controller/controller.ttl +++ b/examples/controller/controller.ttl @@ -16,6 +16,7 @@ bldg:Controller_1 a brick:Controller ; rdfs:label "Main Building Controller" ; brick:hosts bldg:VAV1PointGroup ; brick:controls bldg:VAV1 ; + brick:concerns bldg:Zone1 ; . bldg:VAV1PointGroup a brick:Point_Group ; From c8d0167bbf235bd5826048a32782d986c6f2b53e Mon Sep 17 00:00:00 2001 From: Gabe Fierro Date: Thu, 11 Dec 2025 16:29:54 -0700 Subject: [PATCH 04/15] incorporating feedback on point group model --- bricksrc/collections.py | 6 ++++-- bricksrc/equipment.py | 2 +- bricksrc/relationships.py | 10 +++++----- bricksrc/rules.ttl | 27 +++++++++------------------ examples/controller/controller.ttl | 2 +- 5 files changed, 20 insertions(+), 27 deletions(-) diff --git a/bricksrc/collections.py b/bricksrc/collections.py index 241cab88..3bf1ac3a 100644 --- a/bricksrc/collections.py +++ b/bricksrc/collections.py @@ -62,7 +62,9 @@ }, }, }, - "VRF_System": {"tags": [TAG.Variable, TAG.Refrigerant, TAG.Flow, TAG.System]}, + "VRF_System": { + "tags": [TAG.Variable, TAG.Refrigerant, TAG.Flow, TAG.System] + }, "Refrigeration_System": {"tags": [TAG.Refrigeration, TAG.System]}, "Steam_System": {"tags": [TAG.Steam, TAG.System]}, "Water_System": { @@ -161,7 +163,7 @@ }, "Point_Group": { "tags": [TAG.Collection, TAG.Point_Group], - "constraints": {REC.includes: [BRICK.Point, BRICK.Point_Group]}, + "constraints": {BRICK.hasPart: [BRICK.Point, BRICK.Point_Group]}, }, "System": { "tags": [TAG.Collection, TAG.System], diff --git a/bricksrc/equipment.py b/bricksrc/equipment.py index e42d0ccb..4f6d7b32 100644 --- a/bricksrc/equipment.py +++ b/bricksrc/equipment.py @@ -57,7 +57,7 @@ }, "Controller": { "tags": [TAG.Equipment, TAG.ICT, TAG.Controller], - BRICK.hosts: [BRICK.Point_Group], + BRICK.hostsPoint: [BRICK.Point], "subclasses": { "BACnet_Controller": { "tags": [TAG.Equipment, TAG.BACnet, TAG.Controller], diff --git a/bricksrc/relationships.py b/bricksrc/relationships.py index 59212371..8597fdaa 100644 --- a/bricksrc/relationships.py +++ b/bricksrc/relationships.py @@ -176,18 +176,18 @@ "domain": BRICK.Equipment, RDFS.label: Literal("Is controlled by", lang="en"), }, - "hosts": { + "hostsPoint": { A: [OWL.ObjectProperty, OWL.AsymmetricProperty, OWL.IrreflexiveProperty], OWL.inverseOf: BRICK["isHostedBy"], - "range": BRICK.Point_Group, + "range": BRICK.Point, "domain": BRICK.Controller, - RDFS.label: Literal("Hosts", lang="en"), + RDFS.label: Literal("Hosts point", lang="en"), }, "isHostedBy": { A: [OWL.ObjectProperty, OWL.AsymmetricProperty, OWL.IrreflexiveProperty], - OWL.inverseOf: BRICK["hosts"], + OWL.inverseOf: BRICK["hostsPoint"], "range": BRICK.Controller, - "domain": BRICK.Point_Group, + "domain": BRICK.Point, RDFS.label: Literal("Is hosted by", lang="en"), }, "concerns": { diff --git a/bricksrc/rules.ttl b/bricksrc/rules.ttl index b4ed9176..3f2b3643 100644 --- a/bricksrc/rules.ttl +++ b/bricksrc/rules.ttl @@ -572,22 +572,13 @@ bsh:InheritEVSEChargerDirection a sh:NodeShape ; ] ; . -# check that controllers host the points of the equipment they control -bsh:CheckControllerHostsPointGroups a sh:NodeShape ; - sh:targetClass brick:Controller ; - sh:sparql [ - a sh:SPARQLConstraint ; - sh:message "Controllers should host the points of the equipment they control" ; - sh:prefixes ; - sh:select """ - SELECT $this ?pt ?eq WHERE { - $this brick:controls ?eq . - ?eq brick:hasPoint ?pt . - FILTER NOT EXISTS { - $this brick:hosts ?pg . - ?pg rec:includes ?pt . - } - } - """ ; - ] +# each point can only be hosted by one Controller +bsh:PointHostedByOneController a sh:NodeShape ; + sh:targetClass brick:Point ; + sh:property [ + sh:path brick:isHostedBy ; + sh:class brick:Controller ; + sh:maxCount 1 ; + sh:message "A Brick Point can only be hosted by one Controller" ; + ] ; . diff --git a/examples/controller/controller.ttl b/examples/controller/controller.ttl index bc95104d..43336343 100644 --- a/examples/controller/controller.ttl +++ b/examples/controller/controller.ttl @@ -14,7 +14,7 @@ bldg:Controller_1 a brick:Controller ; rdfs:label "Main Building Controller" ; - brick:hosts bldg:VAV1PointGroup ; + brick:hostsPoint bldg:VAV1_Temperature_Sensor, bldg:VAV1_Occupancy_Sensor ; brick:controls bldg:VAV1 ; brick:concerns bldg:Zone1 ; . From 30825ae68d7c860d73023a202ce6be1be30faf1c Mon Sep 17 00:00:00 2001 From: Gabe Fierro Date: Thu, 11 Dec 2025 16:55:35 -0700 Subject: [PATCH 05/15] add definition --- bricksrc/definitions.csv | 1 + 1 file changed, 1 insertion(+) diff --git a/bricksrc/definitions.csv b/bricksrc/definitions.csv index bef3dba1..15855ac2 100644 --- a/bricksrc/definitions.csv +++ b/bricksrc/definitions.csv @@ -937,6 +937,7 @@ https://brickschema.org/schema/Brick#Plate_Heat_Exchanger,A heat exchanger that https://brickschema.org/schema/Brick#PlugStrip,A device containing a block of electrical sockets allowing multiple electrical devices to be powered from a single electrical socket.,https://en.wikipedia.org/wiki/Power_strip https://brickschema.org/schema/Brick#Plumbing_Room,A service room devoted to the operation and routing of water in a building. Usually distinct from the HVAC subsystems., https://brickschema.org/schema/Brick#Point,, +https://brickschema.org/schema/Brick#Point_Group,"Nestable collections of associated points with a label, e.g. to model associations of points for display, configuration, packaging, and other user-defined needs", https://brickschema.org/schema/Brick#Portfolio,A collection of sites, https://brickschema.org/schema/Brick#Position,The fraction of the full range of motion, https://brickschema.org/schema/Brick#Position_Command,Controls or reports the position of some object, From 27df160bdf5bce19272f52f22d60a039d347d667 Mon Sep 17 00:00:00 2001 From: Gabe Fierro Date: Fri, 12 Dec 2025 10:10:13 -0700 Subject: [PATCH 06/15] remove concerns for now --- bricksrc/relationships.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/bricksrc/relationships.py b/bricksrc/relationships.py index 8597fdaa..63a80df4 100644 --- a/bricksrc/relationships.py +++ b/bricksrc/relationships.py @@ -190,20 +190,6 @@ "domain": BRICK.Point, RDFS.label: Literal("Is hosted by", lang="en"), }, - "concerns": { - A: [OWL.ObjectProperty, OWL.AsymmetricProperty, OWL.IrreflexiveProperty], - OWL.inverseOf: BRICK["isConcernedBy"], - "range": REC.Zone, - "domain": BRICK.Controller, - RDFS.label: Literal("Concerns", lang="en"), - }, - "isConcernedBy": { - A: [OWL.ObjectProperty, OWL.AsymmetricProperty, OWL.IrreflexiveProperty], - OWL.inverseOf: BRICK["concerns"], - "range": BRICK.Controller, - "domain": REC.Zone, - RDFS.label: Literal("Is concerned by", lang="en"), - }, "meters": { A: [OWL.ObjectProperty, OWL.AsymmetricProperty, OWL.IrreflexiveProperty], OWL.inverseOf: BRICK.isMeteredBy, From 670a82964918166452885137c2ea85b3449c6658 Mon Sep 17 00:00:00 2001 From: Gabe Fierro Date: Fri, 12 Dec 2025 10:22:24 -0700 Subject: [PATCH 07/15] make sure we use the correct relationship --- bricksrc/rules.ttl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/bricksrc/rules.ttl b/bricksrc/rules.ttl index 3f2b3643..2f93dc73 100644 --- a/bricksrc/rules.ttl +++ b/bricksrc/rules.ttl @@ -1,4 +1,5 @@ @prefix brick: . +@prefix rec: . @prefix qudt: . @prefix ref: . @prefix rdfs: . @@ -582,3 +583,14 @@ bsh:PointHostedByOneController a sh:NodeShape ; sh:message "A Brick Point can only be hosted by one Controller" ; ] ; . + +# use brick:hasPart to relate Point Groups to their Points, *not* rec:includes +bsh:PointGroupHasPartPoints a sh:NodeShape ; + sh:targetClass brick:Point_Group ; + sh:property [ + sh:path rec:includes ; + sh:class brick:Point ; + sh:message "Use brick:hasPart to relate Point Groups to their Points, not rec:includes" ; + sh:maxCount 0 ; + ] ; +. From fdc1cddf3a9672fafc0b4d34e2c3709660cf49ad Mon Sep 17 00:00:00 2001 From: Gabe Fierro Date: Fri, 12 Dec 2025 11:25:24 -0700 Subject: [PATCH 08/15] fix example --- examples/controller/controller.ttl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/controller/controller.ttl b/examples/controller/controller.ttl index 43336343..51f0a481 100644 --- a/examples/controller/controller.ttl +++ b/examples/controller/controller.ttl @@ -21,7 +21,7 @@ bldg:Controller_1 a brick:Controller ; bldg:VAV1PointGroup a brick:Point_Group ; rdfs:label "VAV1 Point Group" ; - rec:includes bldg:VAV1_Temperature_Sensor, bldg:VAV1_Occupancy_Sensor ; + brick:hasPart bldg:VAV1_Temperature_Sensor, bldg:VAV1_Occupancy_Sensor ; . bldg:VAV1_Temperature_Sensor a brick:Temperature_Sensor ; From bb7a13294490deafb65ba55d646420bf5be19f22 Mon Sep 17 00:00:00 2001 From: Gabe Fierro Date: Fri, 12 Dec 2025 13:39:05 -0700 Subject: [PATCH 09/15] brick hasPart subproperty of rec:includes --- bricksrc/relationships.py | 1 + bricksrc/rules.ttl | 11 ----------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/bricksrc/relationships.py b/bricksrc/relationships.py index 63a80df4..83fd0a4e 100644 --- a/bricksrc/relationships.py +++ b/bricksrc/relationships.py @@ -117,6 +117,7 @@ A: [OWL.ObjectProperty, OWL.AsymmetricProperty, OWL.IrreflexiveProperty], OWL.inverseOf: BRICK["isPartOf"], RDFS.label: Literal("Has part", lang="en"), + RDFS.subPropertyOf: REC.includes, }, "isPartOf": { A: [OWL.ObjectProperty, OWL.AsymmetricProperty, OWL.IrreflexiveProperty], diff --git a/bricksrc/rules.ttl b/bricksrc/rules.ttl index 2f93dc73..c1f0da04 100644 --- a/bricksrc/rules.ttl +++ b/bricksrc/rules.ttl @@ -583,14 +583,3 @@ bsh:PointHostedByOneController a sh:NodeShape ; sh:message "A Brick Point can only be hosted by one Controller" ; ] ; . - -# use brick:hasPart to relate Point Groups to their Points, *not* rec:includes -bsh:PointGroupHasPartPoints a sh:NodeShape ; - sh:targetClass brick:Point_Group ; - sh:property [ - sh:path rec:includes ; - sh:class brick:Point ; - sh:message "Use brick:hasPart to relate Point Groups to their Points, not rec:includes" ; - sh:maxCount 0 ; - ] ; -. From 304650a22bb6ab25e1c0ad96d53924df13e8bef8 Mon Sep 17 00:00:00 2001 From: Gabe Fierro Date: Fri, 12 Dec 2025 15:47:29 -0700 Subject: [PATCH 10/15] handle includes/hasPart: hasPart must exist, includes can get inferred --- bricksrc/rules.ttl | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/bricksrc/rules.ttl b/bricksrc/rules.ttl index 2f93dc73..c257bd14 100644 --- a/bricksrc/rules.ttl +++ b/bricksrc/rules.ttl @@ -584,13 +584,26 @@ bsh:PointHostedByOneController a sh:NodeShape ; ] ; . -# use brick:hasPart to relate Point Groups to their Points, *not* rec:includes -bsh:PointGroupHasPartPoints a sh:NodeShape ; +# if point group rec:includes a point or point group, add brick:hasPart relationship +bsh:PointGroupIncludesHasPart a sh:NodeShape ; sh:targetClass brick:Point_Group ; - sh:property [ - sh:path rec:includes ; - sh:class brick:Point ; - sh:message "Use brick:hasPart to relate Point Groups to their Points, not rec:includes" ; - sh:maxCount 0 ; + sh:rule [ + a sh:SPARQLRule ; + sh:construct """ + CONSTRUCT { + $this brick:hasPart ?part . + } + WHERE { + $this rec:includes ?part . + { + ?part rdf:type/rdfs:subClassOf* brick:Point . + } + UNION + { + ?part rdf:type/rdfs:subClassOf* brick:Point_Group . + } + } + """ ; + sh:prefixes ; ] ; . From a7136354273b5d862c1b022cbe72ed1e8a594d22 Mon Sep 17 00:00:00 2001 From: Gabe Fierro Date: Fri, 12 Dec 2025 16:11:18 -0700 Subject: [PATCH 11/15] remove concerns from example for now --- examples/controller/controller.ttl | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/controller/controller.ttl b/examples/controller/controller.ttl index 51f0a481..14cf9c9b 100644 --- a/examples/controller/controller.ttl +++ b/examples/controller/controller.ttl @@ -16,7 +16,6 @@ bldg:Controller_1 a brick:Controller ; rdfs:label "Main Building Controller" ; brick:hostsPoint bldg:VAV1_Temperature_Sensor, bldg:VAV1_Occupancy_Sensor ; brick:controls bldg:VAV1 ; - brick:concerns bldg:Zone1 ; . bldg:VAV1PointGroup a brick:Point_Group ; From 842095c921a07e499f714c38822007cf2555b932 Mon Sep 17 00:00:00 2001 From: Gabe Fierro Date: Mon, 15 Dec 2025 16:49:17 -0700 Subject: [PATCH 12/15] trying definition --- bricksrc/definitions.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bricksrc/definitions.csv b/bricksrc/definitions.csv index 15855ac2..0ed996a5 100644 --- a/bricksrc/definitions.csv +++ b/bricksrc/definitions.csv @@ -203,7 +203,7 @@ https://brickschema.org/schema/Brick#Conference_Room,A space dedicated in which https://brickschema.org/schema/Brick#Constant_Air_Volume_Box,A terminal unit for which supply air flow rate is constant and the supply air temperature is varied to meet thermal load,https://en.wikipedia.org/wiki/Constant_air_volume https://brickschema.org/schema/Brick#Contact_Sensor,"Senses or detects contact, such as for determining if a door is closed.", https://brickschema.org/schema/Brick#Control_Room,A space from which operations are managed, -https://brickschema.org/schema/Brick#Controller,, +https://brickschema.org/schema/Brick#Controller,An ICT device that exposes Points on a network and implements software to control or monitor equipment or systems using those Points., https://brickschema.org/schema/Brick#Cooling_Coil,"A cooling element made of pipe or tube that removes heat from equipment, machines or airflows. Typically filled with either refrigerant or cold water.", https://brickschema.org/schema/Brick#Cooling_Command,Controls the amount of cooling to be delivered (typically as a proportion of total cooling output), https://brickschema.org/schema/Brick#Cooling_Demand_Sensor,Measures the amount of power consumed by a cooling process; typically found by multiplying the tonnage of a unit (e.g. RTU) by the efficiency rating in kW/ton, From 8c08e50bad972d9dfe076619fed5e00e85b1519d Mon Sep 17 00:00:00 2001 From: Gabe Fierro Date: Tue, 16 Dec 2025 13:51:16 -0700 Subject: [PATCH 13/15] controller -> ict --- bricksrc/relationships.py | 4 ++-- bricksrc/rules.ttl | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bricksrc/relationships.py b/bricksrc/relationships.py index 83fd0a4e..075a8b42 100644 --- a/bricksrc/relationships.py +++ b/bricksrc/relationships.py @@ -181,13 +181,13 @@ A: [OWL.ObjectProperty, OWL.AsymmetricProperty, OWL.IrreflexiveProperty], OWL.inverseOf: BRICK["isHostedBy"], "range": BRICK.Point, - "domain": BRICK.Controller, + "domain": BRICK.ICT_Equipment, RDFS.label: Literal("Hosts point", lang="en"), }, "isHostedBy": { A: [OWL.ObjectProperty, OWL.AsymmetricProperty, OWL.IrreflexiveProperty], OWL.inverseOf: BRICK["hostsPoint"], - "range": BRICK.Controller, + "range": BRICK.ICT_Equipment, "domain": BRICK.Point, RDFS.label: Literal("Is hosted by", lang="en"), }, diff --git a/bricksrc/rules.ttl b/bricksrc/rules.ttl index c257bd14..799f6812 100644 --- a/bricksrc/rules.ttl +++ b/bricksrc/rules.ttl @@ -578,9 +578,9 @@ bsh:PointHostedByOneController a sh:NodeShape ; sh:targetClass brick:Point ; sh:property [ sh:path brick:isHostedBy ; - sh:class brick:Controller ; + sh:class brick:ICT_Equipment ; sh:maxCount 1 ; - sh:message "A Brick Point can only be hosted by one Controller" ; + sh:message "A Brick Point can only be hosted by one piece of ICT Equipment (e.g., a Controller)" ; ] ; . From a05ef989587f5009738c0fd64b4635ff1a45bb82 Mon Sep 17 00:00:00 2001 From: Gabe Fierro Date: Wed, 17 Dec 2025 08:07:30 -0700 Subject: [PATCH 14/15] move hostsPoint --- bricksrc/equipment.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bricksrc/equipment.py b/bricksrc/equipment.py index 4f6d7b32..e3c6f338 100644 --- a/bricksrc/equipment.py +++ b/bricksrc/equipment.py @@ -8,6 +8,7 @@ equipment_subclasses = { "ICT_Equipment": { "tags": [TAG.ICT, TAG.Equipment], + BRICK.hostsPoint: [BRICK.Point], "subclasses": { "ICT_Hardware": { "tags": [TAG.Equipment, TAG.ICT, TAG.Hardware], @@ -57,7 +58,6 @@ }, "Controller": { "tags": [TAG.Equipment, TAG.ICT, TAG.Controller], - BRICK.hostsPoint: [BRICK.Point], "subclasses": { "BACnet_Controller": { "tags": [TAG.Equipment, TAG.BACnet, TAG.Controller], From 6d2fc0eef578a5dd7a25b878172eda92cb84ce09 Mon Sep 17 00:00:00 2001 From: Gabe Fierro Date: Wed, 17 Dec 2025 15:22:18 -0700 Subject: [PATCH 15/15] move shapes around --- bricksrc/equipment.py | 1 + bricksrc/root_class_shapes.ttl | 13 ++++++++++++- bricksrc/rules.ttl | 11 ----------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/bricksrc/equipment.py b/bricksrc/equipment.py index e3c6f338..544098e5 100644 --- a/bricksrc/equipment.py +++ b/bricksrc/equipment.py @@ -58,6 +58,7 @@ }, "Controller": { "tags": [TAG.Equipment, TAG.ICT, TAG.Controller], + BRICK.controls: [BRICK.Equipment], "subclasses": { "BACnet_Controller": { "tags": [TAG.Equipment, TAG.BACnet, TAG.Controller], diff --git a/bricksrc/root_class_shapes.ttl b/bricksrc/root_class_shapes.ttl index f0b62a7c..0296e9eb 100644 --- a/bricksrc/root_class_shapes.ttl +++ b/bricksrc/root_class_shapes.ttl @@ -79,6 +79,11 @@ brick:Equipment a sh:NodeShape ; ); sh:message "A piece of Equipment can feed a Equipment or Location/Space." ]; + sh:property [ + sh:path brick:isControlledBy ; + sh:class brick:Controller ; + sh:message "Equipment can be controlled only by Controllers." + ] ; . brick:Point a sh:NodeShape; @@ -93,7 +98,13 @@ brick:Point a sh:NodeShape; sh:maxCount 0 ; sh:message "Points cannot have locations; use 'isPointOf' instead" ; ] ; - . + sh:property [ + sh:path brick:isHostedBy ; + sh:maxCount 1 ; + sh:class brick:ICT_Equipment ; + sh:message "A Point can be hosted by at most one ICT Equipment." + ] ; +. brick:Collection a sh:NodeShape; sh:node [sh:not [ sh:class brick:Equipment ] ; sh:message "Collection is an exclusive top class." ], diff --git a/bricksrc/rules.ttl b/bricksrc/rules.ttl index 799f6812..f276a02a 100644 --- a/bricksrc/rules.ttl +++ b/bricksrc/rules.ttl @@ -573,17 +573,6 @@ bsh:InheritEVSEChargerDirection a sh:NodeShape ; ] ; . -# each point can only be hosted by one Controller -bsh:PointHostedByOneController a sh:NodeShape ; - sh:targetClass brick:Point ; - sh:property [ - sh:path brick:isHostedBy ; - sh:class brick:ICT_Equipment ; - sh:maxCount 1 ; - sh:message "A Brick Point can only be hosted by one piece of ICT Equipment (e.g., a Controller)" ; - ] ; -. - # if point group rec:includes a point or point group, add brick:hasPart relationship bsh:PointGroupIncludesHasPart a sh:NodeShape ; sh:targetClass brick:Point_Group ;