Niagara PRO TIPS: Schedule Relations Part 2 – Schedule Hierarchies
Video Tutorial: Niagara PRO TIPS: Schedule Relations Part 2 – Schedule Hierarchies
NOTE:
If you want to watch the video while following along with the text notes, then right click and open the video in a new split screen window and the video should appear on the right of the notes so that you can follow along.
Overview
This guide covers building intelligent hierarchies using smart relations and tags in Niagara 4.
Learn how to create both local JACE hierarchies and enterprise supervisor hierarchies using System Database to organize schedules and equipment with dynamic, queryable relationships.
Part 1 Recap: Smart relations setup, tag rules, PX navigation, and BQL grids
Part 2 Focus: Hierarchies at JACE and Supervisor levels using smart relations
Coming in Part 3: BACnet schedule exports (different from imports/links)
Prerequisites
Required Setup from Part 1
Before building hierarchies, ensure you have:
✅ Tag Dictionary - Custom namespace (e.g., b:)
✅ Tag Definitions - b:weeklySchedule, b:scheduleRef
✅ Tag Rules - Applied to occupancy points and schedules
✅ Smart Relations - Weekly Schedule Relation from VComPro
✅ Relations Applied - Visible in Spy Remote as implied relations
Understanding Relation Direction
Critical Concept for Hierarchies
Key Rule: EQL can traverse relations in the same direction but not opposite directions in the same predicate.
Example Relations:
Occupancy Point Perspective:
Inbound Relations:
- end:parentDevice ← (from device)
- b:scheduleRef ← (from schedule)
Why This Matters:
-
Both relations are inbound to the point
-
Can traverse both in same EQL query
-
Can't mix inbound and outbound in same query
Strategy: Use end:parentDevice (inbound) to navigate from points to devices, matching the direction of b:scheduleRef (also inbound).
Part 1: Local JACE Hierarchies
Goal
Create a hierarchy showing:
-
All weekly schedules in the JACE
-
Equipment controlled by each schedule
-
Hierarchical organization for easy navigation
Step 1: Access Hierarchy Service
Location: Services → Hierarchy Service
Purpose: Create custom navigation hierarchies based on tags and relations
Step 2: Create Schedule Hierarchy
-
Drag a Hierarchy component into the Hierarchy Service
-
Name it:
ScheduleHierarchy -
Expand the hierarchy to add levels
Step 3: Add Schedule Query Level
Create Query Level
-
Drag Query Level Def into hierarchy
-
Name it:
Schedules
Configure Query
EQL Query:
b:weeklySchedule
What This Does:
-
Finds all components with
b:weeklySchedulemarker tag -
In this case: schedules under Home/Schedules folder
-
Results: All weekly schedules in station
Why Use b:weeklySchedule Instead of end:schedule:
-
end:schedulematches ALL schedule types (weekly, trigger, day, etc.) -
b:weeklySchedulespecifically matches only weekly schedules -
Provides more precise filtering
Step 4: Add Query Context
Purpose: Store schedule identifier for use in child queries
Understanding Query Context
Query Context is a key-value storage mechanism that:
-
Stores values from parent query results
-
Makes values available to child queries
-
Uses variables referenced with
{variableName} -
Essential for hierarchical filtering
Add Context Variable
-
Select the Schedules query level
-
Find Query Context property
-
Add new key-value pair:
-
Key:
schedID -
Value:
hs:id(the hsID tag)
-
Why Use hs:id Tag:
-
More unique than schedule name
-
Uses handle ORD (guaranteed unique in station)
-
Prevents conflicts from duplicate names
-
Example value:
r:station|slot:/Home/Schedules/FirstFloorWeekly
Alternative: Could use end:name if names are guaranteed unique
Step 5: Add Equipment Query Level
Create Second Query Level
-
Drag another Query Level Def into hierarchy
-
Name it:
Equipment -
Place it as child of Schedules query level
Configure Equipment Query
Complete EQL Query:
hs:equip and end:parentDevice<- and b:scheduleRef<- and hs:id=={schedID}
Breakdown:
Part 1: Find Equipment
hs:equip
-
Finds all components with
hs:equipmarker tag -
In this case: air handler devices
Part 2: Navigate to Control Point
and end:parentDevice<-
-
Inbound parent device relation
-
Coming FROM control point TO device
-
Navigates to: occupancy points under device
Part 3: Navigate to Schedule
and b:scheduleRef<-
-
Inbound schedule ref relation
-
Coming FROM schedule TO point
-
Navigates to: schedule controlling the point
Part 4: Filter by Schedule
and hs:id=={schedID}
-
Check schedule's
hs:idtag -
Must equal
{schedID}from query context -
{...}syntax accesses query context variable -
Matches only equipment controlled by THIS schedule
Visual Path:
Device (hs:equip)
↑ end:parentDevice
Point (occupancy)
↑ b:scheduleRef
Schedule (must match hs:id)
Step 6: Test Local Hierarchy
View Hierarchy
-
Navigate to Hierarchies in station
-
Expand ScheduleHierarchy
-
See all weekly schedules listed
Expand Schedule
-
Select a schedule (e.g., "First Floor Weekly")
-
Expand it
-
See all equipment controlled by that schedule
Example Result:
ScheduleHierarchy
├── First Floor Weekly
│ ├── AH_01
│ ├── AH_02
│ └── AH_03
├── Second Floor Weekly
│ ├── AH_04
│ ├── AH_05
│ └── AH_06
└── Global Boolean Weekly
└── (Equipment list)
Part 2: Enterprise Supervisor Hierarchies
Prerequisites
System Database Setup:
-
System Database Service enabled
-
Niagara Network Indexer configured
-
Global Indexer configured
-
Remote stations indexed
Note: System Database configuration is beyond this tutorial's scope, but indexing is required for hierarchies to work.
Understanding System Database
Purpose:
-
Indexes tags and relations from multiple stations
-
Makes remote station data queryable at supervisor
-
Enables enterprise-level hierarchies
-
Centralizes tag/relation information
Components:
System Index Service:
-
Local Indexer - Indexes local station (supervisor itself)
-
Global Indexer - Indexes remote JACE stations
-
Niagara Network Indexer - Manages remote connections
Step 1: Index Stations
Enable Local Indexer
-
Navigate to: System Index Service
-
Find: Local Indexer
-
Set: Enabled =
true -
Action: Indexes supervisor's local schedules (Global schedules)
What Gets Indexed:
-
Schedules in supervisor (Global Weekly, Global Boolean, etc.)
-
Tags on those schedules
-
Relations from those schedules
Trigger Global Indexer
-
Find: Global Indexer or Niagara Network Indexer
-
Invoke: Index action (or wait for scheduled run)
-
Result: Indexes remote JACE stations
What Gets Indexed:
-
Remote schedules
-
Remote equipment
-
Remote points
-
All tags and relations
Time: May take several minutes for multiple stations
Step 2: Copy Hierarchy from JACE
Initial Setup
-
Navigate to JACE hierarchy service
-
Find your ScheduleHierarchy
-
Copy the hierarchy
-
Navigate to Supervisor hierarchy service
-
Paste the hierarchy
Result: Hierarchy copied but needs modification for system database scope
Step 3: Change Scope to System Database
Understanding Scope
Station Scope (station:):
-
Searches local station only
-
Used in JACE hierarchies
System Database Scope (sys:):
-
Searches system database (indexed data)
-
Includes all indexed stations
-
Used in supervisor hierarchies
Modify Scope
-
Select the ScheduleHierarchy (root level)
-
Find Scope property
-
Change from:
station: -
Change to:
sys:
Alternative: Use SystemDB Hierarchy component from palette (pre-configured with sys: scope)
Step 4: Add Station Grouping
Why Group by Station
Problem:
-
Same schedule names may exist in multiple stations
-
Need to organize by station for clarity
-
Example: "FirstFloorWeekly" in JACE-A and JACE-B
Solution: Add station-level grouping
Add Group Level Def
-
Drag Group Level Def into hierarchy
-
Name it:
Stations -
Configure Value Tag:
end:station
What This Does:
-
Groups components by station name
-
end:stationtag contains station name -
Creates folder for each unique station
Reorder Components
-
Move Stations group level to top (before Schedules)
-
Result: Station folders appear first
Hierarchy Structure:
ScheduleHierarchy
├── Stations (Group by end:station)
│ └── Schedules (Query Level)
│ └── Equipment (Query Level)
Step 5: Test Supervisor Hierarchy
View Hierarchy
-
Navigate to Hierarchies in supervisor
-
Expand ScheduleHierarchy
-
See station folders
Example:
ScheduleHierarchy
├── VComPro Supervisor
│ └── (No schedules - schedules are Global, shown elsewhere)
├── Greenbrier
│ ├── First Floor Weekly
│ │ ├── AH_01
│ │ └── AH_02
│ └── Second Floor Weekly
├── BiconProj Station
│ └── (Schedules from this station)
How It Works
Query Flow:
-
Stations Group - Groups by
end:stationtag -
Schedules Query - Finds
b:weeklyScheduleunder each station -
Equipment Query - Finds equipment with matching
schedID
Result: Organized view of all schedules across all stations with their controlled equipment
Part 3: Handling Imported/Exported Schedules
The Challenge
Scenario:
-
Supervisor has Global schedules (Global Weekly, Global Boolean)
-
JACE imports these schedules via Schedule Device Extension
-
Problem: No relations span between stations
-
Need: Way to connect exported schedules to imported instances
Cannot Do:
Supervisor Global Weekly ---relation---> JACE Imported Global Weekly
Relations don't cross station boundaries!
The Solution: Smart Tags
Strategy:
-
Export Tag - On supervisor schedule, stores station name + slot path
-
Import Tag - On JACE import, stores source station name + supervisor slot path
-
Match Tags - Compare tag values to link schedules
Step 1: Define Import/Export Tags
Add Tag Definitions
In Supervisor Tag Dictionary:
-
Add String Tag:
schedExport -
Add String Tag:
schedImport
In JACE Tag Dictionary:
-
Add String Tag:
schedExport -
Add String Tag:
schedImport
Purpose: Document that these tags exist and may be used
Step 2: Create Import Tag (JACE Side)
Understanding Schedule Import Structure
Navigation Path:
Niagara Network
└── Supervisor Connection
└── Schedule Device Extension
└── Global Weekly (imported schedule)
└── ext (NiagaraScheduleImportExtension)
└── supervisorId (slot path in supervisor)
Key Properties:
-
Parent: Schedule Device Extension
-
Parent.Parent: Station connection (has name)
-
ext.supervisorId: Slot path of schedule in supervisor
Create B Format Smart Tag
Tag Rule Target: Imported schedules (under Schedule Device Extension)
Tag Type: Format Tag (from VComPro palette)
Tag ID: schedImport
B Format Value:
%parent.parent.name%|%ext.supervisorId%?lexicon:baja:ui|dialog.skip
Breakdown:
Part 1: Station Name
%parent.parent.name%
-
Start at imported schedule
-
.parent→ Schedule Device Extension -
.parent→ Station connection -
.name→ Station name (e.g., "VComProSupervisor")
Part 2: Separator
|
-
Hard-coded pipe symbol
Part 3: Supervisor Path
%ext.supervisorId%
-
.ext→ NiagaraScheduleImportExtension child -
.supervisorId→ Slot path in supervisor -
Example:
slot:/GlobalSchedules/GlobalWeekly
Part 4: Fallback for Local Schedules
?lexicon:baja:ui|dialog.skip
-
?→ Conditional (if previous fails) -
lexicon:baja:ui|dialog.skip→ Look up "skip" text -
Prevents errors on local schedules (no import extension)
Result Examples:
Imported Schedule:
schedImport = "VComProSupervisor|slot:/GlobalSchedules/GlobalWeekly"
Local Schedule:
schedImport = "skip"
Step 3: Create Export Tag (Supervisor Side)
Understanding Schedule Export Structure
Navigation Path:
Supervisor
├── GlobalSchedules
│ └── GlobalWeekly (exported schedule)
└── NiagaraNetwork
└── Greenbrier Connection
└── Schedules Extension
└── Schedule Export Manager
└── Schedule Export (references GlobalWeekly)
Goal: Tag on GlobalWeekly with station name + slot path
Create B Format Smart Tag
Tag Rule Target: Global schedules (name starts with "global")
Tag Type: Format Tag (from VComPro palette)
Tag ID: schedExport
B Format Value:
%componentSpace.rootComponent.stationName%|%slotPath%
Breakdown:
Part 1: Station Name
%componentSpace.rootComponent.stationName%
-
componentSpace→ Current component's space -
.rootComponent→ Root of component tree -
.stationName→ Station name -
Result: "VComProSupervisor"
Alternative (Less Flexible):
hardcodedStationName|%slotPath%
But dynamic is better for portability!
Part 2: Separator
|
-
Hard-coded pipe symbol
Part 3: Slot Path
%slotPath%
-
Slot path of this schedule
-
Example:
slot:/GlobalSchedules/GlobalWeekly
Result Example:
schedExport = "VComProSupervisor|slot:/GlobalSchedules/GlobalWeekly"
Match: This exactly matches the schedImport tag value on the JACE!
Step 4: Re-Index After Tag Changes
Important: After modifying tag rules, re-index!
Re-Index Supervisor
-
System Index Service
-
Local Indexer
-
Ensure Enabled =
true -
Indexes local schedules with new
schedExporttags
Re-Index Remote Stations
-
System Index Service
-
Global Indexer or Niagara Network Indexer
-
Invoke Index action
-
Indexes remote JACE schedules with new
schedImporttags
Wait: Indexing may take several minutes
Step 5: Create Exported Schedules Hierarchy
Create New SystemDB Hierarchy
-
Navigate to Supervisor Hierarchy Service
-
Drag SystemDB Hierarchy from palette
-
Name it:
ExportedSchedules
Note: SystemDB Hierarchy pre-configured with sys: scope
Add Schedules Query Level
-
Drag Query Level Def into hierarchy
-
Name it:
Schedules
EQL Query:
b:weeklySchedule and b:schedExport
What This Does:
-
Finds weekly schedules
-
That have
b:schedExporttag (exported schedules) -
Result: Global schedules in supervisor
Add Query Context
On Schedules Query Level:
Key: schedExport
Value:b:schedExport
Purpose: Store the export tag value (station + path) for matching
Add Station Grouping
-
Drag Group Level Def into hierarchy
-
Name it:
Stations -
Value Tag:
end:station -
Include Empty Groups:
true
Result: Shows all stations even if no equipment matches
Add Equipment Query Level
-
Drag Query Level Def into hierarchy
-
Name it:
Equipment
EQL Query:
hs:equip and end:parentDevice<- and b:scheduleRef<- and b:schedImport=={schedExport}
Breakdown:
Parts 1-3: Same as before (find equipment, navigate through point to schedule)
Part 4: Match Import to Export
and b:schedImport=={schedExport}
-
Check imported schedule's
b:schedImporttag -
Must equal
{schedExport}from query context -
Matches: "VComProSupervisor|slot:/GlobalSchedules/GlobalWeekly"
-
Result: Only equipment controlled by imported instance of THIS export
Step 6: Test Exported Schedules Hierarchy
View Hierarchy
-
Navigate to Hierarchies in supervisor
-
Expand ExportedSchedules
-
See Global schedules (e.g., "Global Weekly")
Expand Schedule
-
Expand a Global schedule
-
See station folders
-
Expand a station folder
-
See equipment in that JACE controlled by the imported schedule
Example:
ExportedSchedules
└── Global Weekly
├── Greenbrier
│ ├── AH_01
│ ├── AH_02
│ └── AH_03
└── BiconProj Station
├── AH_10
└── AH_11
Meaning: Global Weekly is imported into both stations and controls listed equipment
Query Context Advanced Usage
What is Query Context?
Query Context is a variable storage mechanism in hierarchies:
-
Stores values from parent query results
-
Makes values available to child/descendant queries
-
Referenced using
{variableName}syntax -
Essential for hierarchical filtering
Creating Query Context Variables
Location: Query Level Def properties
Structure:
Key: variableName (any string)
Value: tag or property reference
Examples:
Key: schedID
Value: hs:id
Key: schedExport
Value: b:schedExport
Key: floorName
Value: end:floorName
Accessing Query Context
Syntax in Child Queries:
{variableName}
Must use curly braces, not parentheses!
Examples:
hs:id=={schedID}
b:schedImport=={schedExport}
end:floor=={floorName}
B Format Syntax Reference
Basic B Format
Purpose: Dynamic string construction with property values
Syntax:
%propertyPath%
Navigation Operators
Property Access:
%parent.name% → Parent object's name property
%ext.supervisorId% → Child ext object's supervisorId property
%parent.parent.name% → Grandparent's name
Special Properties:
%name% → Object's name
%displayName% → Display name
%slotPath% → Slot path
%handle% → Handle
Component Space Navigation
Root Component:
%componentSpace.rootComponent.stationName%
Components:
-
componentSpace→ Current component's space -
rootComponent→ Root of tree -
Properties available on root
Conditional Fallback
Syntax:
%expression%?fallbackValue
Example:
%ext.supervisorId%?unknown
Lexicon Lookup:
%expression%?lexicon:module|key
Example:
%parent.name%?lexicon:baja:ui|dialog.skip
Result: If expression fails, use lexicon value
Hierarchy Best Practices
Organizing Hierarchies
Do:
✅ Use station grouping for enterprise hierarchies
✅ Name query levels descriptively
✅ Add query context for filtering
✅ Use include empty groups to show all stations
✅ Test with subset before full deployment
Don't:
❌ Create overly deep hierarchies (>4 levels)
❌ Use absolute ORDs in query context
❌ Forget to re-index after tag changes
❌ Mix station: and sys: scopes incorrectly
Query Context Strategy
When to Use:
-
Filtering child queries based on parent results
-
Matching across tag values
-
Creating dynamic hierarchies
-
Multi-level organization
Naming Conventions:
-
Use descriptive variable names
-
Match tag names when possible
-
Document in hierarchy description
System Database Indexing
Index Triggers:
-
After tag rule changes
-
After relation definition changes
-
After adding new stations
-
Periodically (scheduled)
Best Practice:
-
Index locally first (supervisor)
-
Then trigger global index
-
Wait for completion before testing
-
Monitor index status
Troubleshooting
Hierarchy Shows No Results
Problem: Query returns empty
Possible Causes:
-
Tags not applied
-
Wrong scope (station: vs sys:)
-
Not indexed in system database
-
Query syntax error
Solutions:
-
Verify tags on components (Spy Remote)
-
Confirm scope matches intent
-
Re-index stations
-
Test query in simpler form
Query Context Variable Not Working
Problem: {variable} not matching
Possible Causes:
-
Wrong bracket type (used
()instead of{}) -
Variable name typo
-
Variable not defined in parent
-
Tag value format mismatch
Solutions:
-
Use curly braces
{var}, not parentheses -
Check variable name spelling
-
Verify query context exists on parent
-
Compare actual tag values
Import/Export Tags Not Matching
Problem: Equipment not showing under exported schedule
Possible Causes:
-
Tag format differs (station name, separator)
-
Not re-indexed after tag creation
-
B format syntax error
-
Import extension missing
Solutions:
-
Check both tag values match exactly
-
Re-index supervisor and JACE
-
Test B format on single component
-
Verify import extension exists
Empty Station Folders
Problem: Station folders appear but no equipment shown
Possible Causes:
-
include empty groups= false -
No equipment actually matches
-
Query filtering too strict
Solutions:
-
Set
include empty groups= true -
Verify equipment tags
-
Test simpler query first
-
Check relation traversal
Key Takeaways
✅ Local hierarchies use station: scope for JACE organization
✅ Enterprise hierarchies use sys: scope for supervisor
✅ Query context enables parent-child filtering
✅ Relation direction must be consistent in same query
✅ Smart tags (B format) enable import/export matching
✅ System database must be indexed before queries work
✅ Group Level Def organizes by tag values (stations)
✅ Relations don't span stations - use tags instead
✅ Curly braces {} access query context variables
✅ Re-index after any tag rule changes
Complete Workflow Summary
Local JACE Hierarchy
1. Create Hierarchy
2. Add Schedule Query Level (b:weeklySchedule)
3. Add Query Context (schedID = hs:id)
4. Add Equipment Query Level
(hs:equip and end:parentDevice<- and b:scheduleRef<- and hs:id=={schedID})
5. Test hierarchy
Enterprise Supervisor Hierarchy
1. Index stations (local + global)
2. Copy JACE hierarchy to supervisor
3. Change scope to sys:
4. Add Station Group Level (end:station)
5. Reorder (Stations first)
6. Test hierarchy
Import/Export Hierarchy
1. Define schedImport/schedExport tags
2. Create import tag rule (JACE)
B format: %parent.parent.name%|%ext.supervisorId%
3. Create export tag rule (Supervisor)
B format: %componentSpace.rootComponent.stationName%|%slotPath%
4. Re-index all stations
5. Create SystemDB hierarchy
6. Add Schedules query (b:weeklySchedule and b:schedExport)
7. Add Query Context (schedExport = b:schedExport)
8. Add Station grouping
9. Add Equipment query
(hs:equip and end:parentDevice<- and b:scheduleRef<- and b:schedImport=={schedExport})
10. Test hierarchy
Coming in Part 3
The next video will cover:
-
BACnet schedule exports (different from imports/links)
-
Handling schedule objects vs. schedule links
-
Special considerations for BACnet integration
-
Export-specific tag strategies
Quick Reference
Hierarchy Scopes
station: → Local JACE search
sys: → System database search (enterprise)
Query Context Access
Define: Key = variableName, Value = tag
Use: tagName=={variableName}
Must use {} not ()!
B Format Patterns
Property: %propertyName%
Navigation: %parent.child.property%
Slot Path: %slotPath%
Station: %componentSpace.rootComponent.stationName%
Fallback: %expression%?defaultValue
Lexicon: %expression%?lexicon:module|key
Common EQL Patterns
Find Equipment:
hs:equip
Navigate Relations (same direction):
end:parentDevice<- and b:scheduleRef<-
Filter by Variable:
hs:id=={schedID}
Presenter: James Johnson
Series:Niagara PRO TIPS
Topic:Schedule Relations Part 2 – Schedule Hierarchies
Part:2 of 3
Key Concept:Building intelligent hierarchies at JACE and supervisor levels using smart relations, query context, and system database to organize schedules and equipment dynamically
YouTube: http://www.youtube.com/@TridiumInc