Appearance
Build an HVAC scheduling application
This walkthrough documents the hvac_schedules reference application. It lets a customer edit zone configuration in the cloud and projects the current records into a versioned dataset that a Linux controller can use offline.
Implementation boundary
The proof uses the real customer record API, dataset generator, Prelude Agent Product Runtime, persistent dataset store, and applied-generation reporting. The proof harness substitutes a simulator at the OEM controller boundary. It reads the active dataset but does not run a building control or safety loop.
This guide uses the shared Product Applications status vocabulary:
- Platform-provided and proven: customer-scoped records, immutable dataset generations, agent download/activation, applied reporting, and persistence across the harness's agent restart.
- Worked reference / test-mode: the editable HVAC starter and its minimal
zone/setpoint_cprojection. - Simulated in the proof harness: the OEM controller consumer reads the agent's active
hvac_entitlementsdataset. - Customer-supplied: calendar semantics, local control and safety loops, setpoint validation, physical HVAC integration, and fallback policy.
You finish with:
- an HVAC Controller Device Class bound as
controller - customer-managed
schedulerecords - an
hvac_entitlementsoffline dataset - a published application instance for one building
- desired and applied generation evidence for a staging controller
The reference proves non-financial offline dataset sync. It does not implement a complete BMS, calendar engine, occupancy strategy, safety loop, or local control algorithm.
Before you start
You need:
- Product Applications beta access on Standard+
- a staging customer and Customer Portal
- an HVAC Controller Device Class
- a representative Linux controller or safe simulator
- a controller-side consumer that can validate and atomically activate a versioned JSON dataset
Use hvac-sim for Device Class telemetry. Prelude Agent Product Runtime consumes the HVAC entitlements dataset; the controller OEM handler reads the active records over the local Unix socket.
Part 1: Define the controller product
Create or select HVAC Controller under Engineering > Device classes. Define the product values and controls independently from the schedule records:
- current zone temperature
- operating mode and fault state
- customer-safe bounded override where supported
- reported schedule generation
- connectivity and data freshness
The customer schedule says what should be true. The controller remains responsible for local limits, frost protection, compressor protection, sensor validation, and safe fallback.

Part 2: Create and bind the application
- Open Developer > Product Applications.
- Create HVAC Schedules with key
hvac_schedules. - Open Build > Hardware.
- Connect the HVAC Controller class with role alias
controller. - Confirm the staging controller is eligible for that role.


Part 3: Define schedule records
In Build > Models, add:
| Field | Value |
|---|---|
| Model key | schedule |
| Label | Schedule |
| Lifecycle | Configuration |
| Customer create/update | Enabled for authorised operators |
The normative minimum fields are:
| Field key | Type | Meaning |
|---|---|---|
zone | String | Zone identifier understood by the controller |
setpoint_c | Integer | Temperature target in degrees Celsius |
A production schedule normally also needs:
- a stable schedule or rule ID
- days of week and local start/end times
- an IANA time-zone name
- occupied and unoccupied setpoints
- validity dates and exception dates
- priority and temporary override expiry
- a controller, site, or group reference
Keep the first proof deliberately small. Adding calendar semantics without explicit time-zone and daylight-saving behavior creates an unsafe ambiguity.
Part 4: Define the offline dataset
Add an offline dataset:
| Setting | Value |
|---|---|
| Key | hvac_entitlements |
| Label | HVAC entitlements |
| Projection | schedule.zone, schedule.setpoint_c |
| Format | JSON |
The name comes from the normative reference. For a customer-facing production design, use wording such as HVAC schedule dataset in the UI while retaining a stable technical key once devices depend on it.
Each generated payload is immutable and identified as a generation. The cloud tracks desired and reported applied generation separately.
Prelude Agent Product Runtime downloads each generation advertised on instance discovery, verifies it, stages it, atomically activates it, keeps last-known-good, and reports the applied generation. After a reboot the same identity volume must reopen the last applied generation without a duplicate apply. Confirm the Customer Portal sync chip shows current.

hvac_entitlements dataset consumed by the local agent simulator.Part 5: Add customer pages and permissions
In Access:
- add a list page for schedules
- add create and edit forms for the approved fields
- allow viewers to read but not change schedules
- allow only authorised operators to create or update
- keep dataset generation and device sync controls in the OEM or administrator surface
Show the customer:
- zone and target
- when the configuration was changed
- who changed it
- desired generation
- applied generation and last report
- an explicit pending, current, failed, or stale sync state
Do not present a saved cloud record as proof that the building controller applied it.
Part 6: Publish and prove the first generation
- Validate and publish version 1.
- Attach the version to the staging Customer Portal.
- Provision the Building A customer instance.
- Create a record with
zone = lobbyandsetpoint_c = 21. - In Release > Sandbox, preview
hvac_entitlements. - Generate the base dataset for the staging controller.
- Inspect the payload and record count.
- Have the test consumer validate and activate the generation.
- Report that exact generation as applied.
- Confirm the device sync state becomes current.
The normative acceptance proof expects one record in the first base generation and a current applied state after the report.
Part 7: Prove change and failure behavior
Update the lobby setpoint, then generate the next dataset.
Confirm:
- a new immutable generation is created
- the previous generation remains available as evidence
- the controller reports pending until it applies the new generation
- successful activation changes reported generation
- invalid content leaves the last-known-good schedule active
- a failed report does not claim current state
- duplicate generation fetch or applied reports are safe
- a second customer cannot fetch Building A's dataset
Then test:
- controller offline during a schedule change
- power loss while staging
- restart after successful activation
- unsupported schema version
- out-of-range setpoint
- missing zone
- rollback to the last-known-good generation
The local agent and simulator provide real desired/applied generation reports and last-known-good restart evidence. They do not implement a BMS safety loop or prove that a compressor, valve, or fan followed the schedule. Capture that physical evidence only during controller qualification.
Part 8: Extend toward a production HVAC workflow
Add complexity one contract at a time:
- model time zone and recurrence explicitly
- add temporary overrides with expiry
- publish telemetry and explicit fault state through the Device Class
- add rules for customer-impacting conditions
- add operations for approved overrides
- add multi-controller targeting only after partial rollout and rollback are tested
- preserve a local fallback schedule for cloud and network failure
Do not put the safety loop or second-by-second control process in Product Applications. Keep it local to the qualified controller.
Production handover gate
- [ ] Every schedule has explicit time-zone and daylight-saving behavior.
- [ ] Setpoints and overrides are bounded locally.
- [ ] The controller activates datasets atomically.
- [ ] Last-known-good state survives restart and failed updates.
- [ ] Desired and applied generations are shown separately.
- [ ] Offline, stale, pending, current, and failed states differ.
- [ ] Customer viewers cannot edit schedules.
- [ ] Another customer cannot see records, datasets, devices, or activity.
- [ ] Rollback and schema compatibility are tested.
- [ ] Local safety and fallback do not depend on cloud availability.