Customer Knowledge Base
Breadcrumbs

Niagara PRO TIPS: Schedule Relations Part 2 Schedule Hierarchies

image-20260129-155517.png

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:

  1. All weekly schedules in the JACE

  2. Equipment controlled by each schedule

  3. 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

  1. Drag a Hierarchy component into the Hierarchy Service

  2. Name it: ScheduleHierarchy

  3. Expand the hierarchy to add levels


Step 3: Add Schedule Query Level

Create Query Level

  1. Drag Query Level Def into hierarchy

  2. Name it: Schedules

Configure Query

EQL Query:

b:weeklySchedule

What This Does:

  • Finds all components with b:weeklySchedule marker tag

  • In this case: schedules under Home/Schedules folder

  • Results: All weekly schedules in station

Why Use b:weeklySchedule Instead of end:schedule:

  • end:schedule matches ALL schedule types (weekly, trigger, day, etc.)

  • b:weeklySchedule specifically 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

  1. Select the Schedules query level

  2. Find Query Context property

  3. 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

  1. Drag another Query Level Def into hierarchy

  2. Name it: Equipment

  3. 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:equip marker 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:id tag

  • 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

  1. Navigate to Hierarchies in station

  2. Expand ScheduleHierarchy

  3. See all weekly schedules listed

Expand Schedule

  1. Select a schedule (e.g., "First Floor Weekly")

  2. Expand it

  3. 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

  1. Navigate to: System Index Service

  2. Find: Local Indexer

  3. Set: Enabled = true

  4. 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

  1. Find: Global Indexer or Niagara Network Indexer

  2. Invoke: Index action (or wait for scheduled run)

  3. 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

  1. Navigate to JACE hierarchy service

  2. Find your ScheduleHierarchy

  3. Copy the hierarchy

  4. Navigate to Supervisor hierarchy service

  5. 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

  1. Select the ScheduleHierarchy (root level)

  2. Find Scope property

  3. Change from: station:

  4. 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

  1. Drag Group Level Def into hierarchy

  2. Name it: Stations

  3. Configure Value Tag: end:station

What This Does:

  • Groups components by station name

  • end:station tag contains station name

  • Creates folder for each unique station

Reorder Components

  1. Move Stations group level to top (before Schedules)

  2. 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

  1. Navigate to Hierarchies in supervisor

  2. Expand ScheduleHierarchy

  3. 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:

  1. Stations Group - Groups by end:station tag

  2. Schedules Query - Finds b:weeklySchedule under each station

  3. 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:

  1. Export Tag - On supervisor schedule, stores station name + slot path

  2. Import Tag - On JACE import, stores source station name + supervisor slot path

  3. Match Tags - Compare tag values to link schedules


Step 1: Define Import/Export Tags

Add Tag Definitions

In Supervisor Tag Dictionary:

  1. Add String Tag: schedExport

  2. Add String Tag: schedImport

In JACE Tag Dictionary:

  1. Add String Tag: schedExport

  2. 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

  1. System Index Service

  2. Local Indexer

  3. Ensure Enabled = true

  4. Indexes local schedules with new schedExport tags

Re-Index Remote Stations

  1. System Index Service

  2. Global Indexer or Niagara Network Indexer

  3. Invoke Index action

  4. Indexes remote JACE schedules with new schedImport tags

Wait: Indexing may take several minutes


Step 5: Create Exported Schedules Hierarchy

Create New SystemDB Hierarchy

  1. Navigate to Supervisor Hierarchy Service

  2. Drag SystemDB Hierarchy from palette

  3. Name it: ExportedSchedules

Note: SystemDB Hierarchy pre-configured with sys: scope


Add Schedules Query Level

  1. Drag Query Level Def into hierarchy

  2. Name it: Schedules

EQL Query:

b:weeklySchedule and b:schedExport

What This Does:

  • Finds weekly schedules

  • That have b:schedExport tag (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

  1. Drag Group Level Def into hierarchy

  2. Name it: Stations

  3. Value Tag: end:station

  4. Include Empty Groups: true

Result: Shows all stations even if no equipment matches


Add Equipment Query Level

  1. Drag Query Level Def into hierarchy

  2. 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:schedImport tag

  • 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

  1. Navigate to Hierarchies in supervisor

  2. Expand ExportedSchedules

  3. See Global schedules (e.g., "Global Weekly")

Expand Schedule

  1. Expand a Global schedule

  2. See station folders

  3. Expand a station folder

  4. 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%

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