Spaxiom Logo
Spaxiom Use Case - Appendix A.8

Building HVAC & Occupancy Optimization

Using Spaxiom for Demand-Responsive Climate Control and Energy Efficiency

Joe Scanlin

November 2025

About Spaxiom & INTENT

Spaxiom is a sensor abstraction layer and runtime that translates billions of heterogeneous sensor streams into structured, semantic events. It provides a spatial-temporal DSL for defining zones, entities, and conditions, making it easy to build context-aware applications across industries.

INTENT (Intelligent Network for Temporal & Embodied Neuro-symbolic Tasks) is Spaxiom's high-level event vocabulary. Instead of overwhelming AI agents with raw sensor data, Spaxiom emits compact, meaningful events that agents can immediately understand and act upon.

TL;DR

Commercial buildings consume 40% of total U.S. energy, with HVAC systems accounting for 40–60% of that usage. Traditional Building Automation Systems (BAS) operate on fixed schedules and static temperature setpoints, conditioning empty spaces and responding slowly to occupancy changes. The challenge is that thermostats and VAV controllers run proprietary BACnet or Modbus protocols in isolated loops, occupancy sensors feed separate access control systems, CO₂ monitors log to dedicated IAQ platforms, and outdoor weather stations connect to independent forecast services—leaving AI agents unable to correlate real-time occupancy patterns with HVAC demand across fragmented building systems.

Spaxiom fuses occupancy sensors (motion, badge access, Wi-Fi/BLE tracking), indoor environmental quality monitors (temperature, humidity, CO₂, VOCs), HVAC system telemetry (AHU status, VAV damper positions, chiller loads), and outdoor weather feeds into one intelligent climate control platform. Instead of heating vacant conference rooms at 6 AM because of rigid schedules, it calculates a real-time "Comfort Efficiency Index" that balances occupant thermal comfort (PMV/PPD models) with energy consumption, predicting room usage patterns 30–60 minutes ahead. This sends control signals like "meeting room 4B unoccupied for next 2 hours—reduce setpoint to 18°C" or "east wing occupancy spike detected—pre-cool spaces now to avoid thermal lag," helping facility managers reduce HVAC energy costs by 20–35% while improving occupant comfort through responsive, human-centric climate control.

A.8 Building HVAC & Occupancy Optimization

A.8.1 Context & Sensors

Commercial buildings (offices, hospitals, universities, retail) consume approximately 40% of total energy in developed nations, with Heating, Ventilation, and Air Conditioning (HVAC) systems representing 40–60% of building energy use. Traditional Building Automation Systems (BAS) operate on time-based schedules with fixed temperature setpoints, resulting in significant waste: conditioning spaces during unoccupied periods, failing to pre-cool/pre-heat before occupancy surges, and responding reactively to thermal discomfort complaints rather than proactively optimizing for predicted usage patterns.

Modern smart buildings integrate heterogeneous sensor networks spanning occupancy detection, environmental monitoring, and HVAC system state:

  • Occupancy sensors: Passive infrared (PIR) motion detectors, ultrasonic sensors, badge/card access systems, Wi-Fi/BLE device tracking, computer vision (camera-based people counting)
  • Temperature sensors: Zone thermostats, supply/return air temperature probes, radiant floor sensors
  • IAQ sensors: CO₂ concentration (occupancy proxy and ventilation indicator), relative humidity, VOC (volatile organic compounds), PM2.5 particulates
  • HVAC system telemetry: Air Handling Unit (AHU) fan speeds and damper positions, Variable Air Volume (VAV) box airflow rates and reheat coil status, chiller/boiler plant loads and efficiency
  • Outdoor weather: Temperature, humidity, solar irradiance, wind speed (for economizer control and predictive load forecasting)
  • Utility meters: Real-time electricity demand (kW) and cumulative energy (kWh) for demand response integration

Legacy BAS protocols (BACnet, Modbus, LonWorks) operate in isolated control loops with limited cross-system integration. Spaxiom enables predictive, occupancy-driven HVAC orchestration by fusing real-time occupancy patterns, thermal comfort models, and HVAC system dynamics to minimize energy consumption while maintaining human-centric comfort standards.

A.8.2 INTENT Layer Events

The building HVAC domain defines semantic events that abstract low-level sensor data into actionable facility management directives:

  • ZoneOccupied / ZoneVacant: High-confidence occupancy state transitions based on multi-modal sensor fusion (motion + CO₂ rise + badge access). Includes occupancy count estimate and predicted duration (e.g., "meeting room occupied for next 90 min based on calendar integration").
  • ThermalDiscomfort: Detected when Predicted Mean Vote (PMV) exceeds ±0.7 (outside ASHRAE 55 comfort range), indicating occupants likely experiencing thermal dissatisfaction. Includes root cause analysis (insufficient airflow, setpoint deviation, solar heat gain).
  • VentilationDeficit: CO₂ concentration exceeds 1000 ppm (ASHRAE 62.1 guideline for acceptable IAQ), indicating inadequate outdoor air ventilation for current occupancy level. Triggers AHU outdoor air damper increase.
  • PreConditioningRequired: Predictive event fired 30–60 minutes before anticipated occupancy surge (based on calendar, historical patterns, or detected arrival trends), allowing HVAC system to ramp thermal capacity before occupants arrive.
  • EconomizerOpportunity: Outdoor air temperature and humidity conditions favorable for "free cooling"—meeting space cooling needs by increasing outdoor air intake rather than mechanical refrigeration. Significant energy savings during shoulder seasons.
  • DemandResponseEvent: Utility-issued grid stress signal (peak demand period, high electricity price) triggers non-critical load shedding: raising cooling setpoints by 2–3°C, pre-cooling thermal mass before event, or shifting ventilation to minimum code requirements.

These events enable closed-loop HVAC control, integration with calendar/scheduling systems for predictive conditioning, and participation in utility demand response programs for energy cost optimization.

A.8.3 Fusion Metrics: Comfort Efficiency Index

Optimizing HVAC systems requires balancing two competing objectives: minimizing energy consumption while maintaining occupant thermal comfort. We compute a Comfort Efficiency Index (CEI) that quantifies this trade-off:

CEI(z, t) = wC · ηcomfort(z, t) + wE · ηenergy(z, t) + wQ · ηIAQ(z, t)

where each component is normalized to [0,1] with 1 = optimal performance:

Comfort Efficiency: Based on ASHRAE 55 Predicted Mean Vote (PMV) thermal comfort model:

ηcomfort(z, t) = max(0, 1 − |PMV(z, t)| / PMVmax)

where PMV is computed from operative temperature, humidity, air velocity, metabolic rate, and clothing insulation. PMV = 0 indicates thermal neutrality, PMV = ±0.5 is "slightly warm/cool" (acceptable), and |PMV| > 1.0 indicates discomfort. We set PMVmax = 1.5 for normalization.

The full PMV calculation (Fanger model) integrates six thermal factors:

PMV = [0.303 · e−0.036·M + 0.028] · L

where M is metabolic rate (W/m²), and L is the thermal load on the body accounting for convection, radiation, evaporation, and respiration heat exchange. Simplified for typical office environments (M ≈ 1.2 met, clothing ≈ 0.7 clo), PMV ≈ 0.5 · (Top − 23°C) where Top is operative temperature.

Energy Efficiency: Compares actual HVAC energy consumption to a baseline model:

ηenergy(z, t) = max(0, 1 − (Eactual(t) − Eoptimal(t)) / Ebaseline(t))

where Eactual is measured HVAC power draw, Eoptimal is the theoretical minimum to maintain comfort given outdoor conditions and occupancy, and Ebaseline is historical energy use for the same conditions under legacy control (typically time-scheduled operation).

Indoor Air Quality: Weighted combination of CO₂, humidity, and VOC levels:

ηIAQ(z, t) = 0.5 · (1 − CO₂excess / 600 ppm) + 0.3 · ηRH + 0.2 · ηVOC

where CO₂excess = max(0, CO₂ − 800 ppm), ηRH penalizes humidity outside 30–60% range, and ηVOC normalizes total VOC concentration against health thresholds.

A CEI above 0.85 indicates optimal HVAC performance, 0.70–0.85 suggests tuning opportunities, below 0.70 triggers HvacInefficiency investigation.

A.8.4 Spaxiom DSL Implementation

The BuildingZone class demonstrates occupancy-driven HVAC optimization with predictive pre-conditioning:

from spaxiom import Sensor, Intent, Fusion, Metric, Zone
import math
from datetime import datetime, timedelta

class BuildingZone:
    def __init__(self, zone_id, area_m2, design_occupancy):
        self.zone_id = zone_id
        self.area_m2 = area_m2
        self.design_occupancy = design_occupancy

        # Sensor streams
        self.motion_sensors = [Sensor(f"pir_{i}") for i in range(4)]
        self.badge_reader = Sensor("badge_access")
        self.thermostat = Sensor("thermostat")
        self.co2_sensor = Sensor("co2_monitor")
        self.humidity_sensor = Sensor("humidity")
        self.vav_box = Sensor("vav_controller")  # Variable Air Volume
        self.outdoor_weather = Sensor("weather_station")

        # INTENT events
        self.zone_occupied = Intent("ZoneOccupied")
        self.zone_vacant = Intent("ZoneVacant")
        self.thermal_discomfort = Intent("ThermalDiscomfort")
        self.ventilation_deficit = Intent("VentilationDeficit")
        self.preconditioning_required = Intent("PreConditioningRequired")
        self.economizer_opportunity = Intent("EconomizerOpportunity")

        # Fusion metrics
        self.cei = Metric("comfort_efficiency_index", range=(0, 1))
        self.pmv = Metric("predicted_mean_vote", range=(-3, 3))
        self.occupancy_count = Metric("occupancy_estimate", range=(0, design_occupancy))

        # State tracking
        self.current_occupancy = 0
        self.is_occupied = False
        self.last_motion_time = None
        self.co2_ppm = 400  # Outdoor baseline
        self.temperature_c = 21
        self.setpoint_c = 22
        self.hvac_power_kw = 0

    @Fusion.rule
    def estimate_occupancy(self):
        """Multi-modal occupancy fusion from motion, CO₂, and badge access"""
        # Motion-based occupancy (binary per sensor)
        motion_active = sum(1 for sensor in self.motion_sensors
                           if sensor.latest().get("motion_detected", False))
        motion_confidence = min(1.0, motion_active / len(self.motion_sensors))

        # CO₂-based occupancy estimate (assumes ~35 L/h CO₂ per person)
        co2_excess = max(0, self.co2_ppm - 400)  # Above outdoor baseline
        co2_occupancy_estimate = co2_excess / 35.0  # Rough person count
        co2_confidence = min(1.0, co2_occupancy_estimate / self.design_occupancy)

        # Badge access (recent entries minus exits)
        badge_data = self.badge_reader.latest()
        badge_count = badge_data.get("current_count", 0)
        badge_confidence = 0.9 if badge_count > 0 else 0.1

        # Weighted fusion (badge is most reliable, CO₂ and motion are supporting)
        w_badge, w_co2, w_motion = 0.5, 0.3, 0.2
        fused_confidence = (w_badge * badge_confidence +
                           w_co2 * co2_confidence +
                           w_motion * motion_confidence)

        # Occupancy count estimate (prioritize badge count if available)
        if badge_count > 0:
            estimated_count = badge_count
        else:
            estimated_count = int(co2_occupancy_estimate)

        self.current_occupancy = estimated_count
        self.occupancy_count.update(estimated_count)

        # Emit occupancy state transitions
        newly_occupied = fused_confidence > 0.6 and not self.is_occupied
        newly_vacant = fused_confidence < 0.3 and self.is_occupied

        if newly_occupied:
            self.is_occupied = True
            self.zone_occupied.emit(
                zone_id=self.zone_id,
                occupancy_count=estimated_count,
                confidence=fused_confidence,
                timestamp=datetime.now()
            )
        elif newly_vacant:
            self.is_occupied = False
            self.zone_vacant.emit(
                zone_id=self.zone_id,
                vacant_duration_min=0,  # Will be updated by timer
                timestamp=datetime.now()
            )

        return estimated_count

    @Fusion.rule
    def calculate_pmv(self):
        """Compute Predicted Mean Vote thermal comfort index"""
        # Simplified PMV for typical office (M=1.2 met, clo=0.7)
        T_op = self.temperature_c  # Operative temp ≈ air temp (low radiation)
        rh = self.humidity_sensor.latest().get("relative_humidity", 50)

        # Simplified Fanger model for sedentary office work
        # PMV ≈ 0.5 * (T_op - T_neutral) adjusted for humidity
        T_neutral = 23.0  # Thermal neutrality for office conditions
        pmv_value = 0.5 * (T_op - T_neutral) + 0.01 * (rh - 50)

        self.pmv.update(pmv_value)

        # Detect thermal discomfort (|PMV| > 0.7 per ASHRAE 55)
        if abs(pmv_value) > 0.7:
            severity = "MINOR" if abs(pmv_value) < 1.0 else "MAJOR"
            cause = "TOO_WARM" if pmv_value > 0 else "TOO_COLD"

            self.thermal_discomfort.emit(
                zone_id=self.zone_id,
                pmv=pmv_value,
                temperature_c=T_op,
                setpoint_c=self.setpoint_c,
                severity=severity,
                cause=cause,
                action="ADJUST_SETPOINT_OR_AIRFLOW"
            )

        return pmv_value

    @Fusion.rule
    def calculate_cei(self):
        """Compute Comfort Efficiency Index balancing comfort, energy, IAQ"""
        # Comfort component (from PMV)
        pmv_val = self.calculate_pmv()
        eta_comfort = max(0, 1 - abs(pmv_val) / 1.5)

        # Energy efficiency (compare to baseline)
        # Baseline: 20 W/m² for typical office HVAC
        E_baseline = 20 * self.area_m2 / 1000  # kW
        E_actual = self.hvac_power_kw
        # Optimal: scale with occupancy (empty space needs minimal conditioning)
        occupancy_fraction = self.current_occupancy / self.design_occupancy
        E_optimal = E_baseline * (0.3 + 0.7 * occupancy_fraction)  # 30% base load

        if E_baseline > 0:
            eta_energy = max(0, 1 - (E_actual - E_optimal) / E_baseline)
        else:
            eta_energy = 1.0

        # IAQ component
        co2_excess = max(0, self.co2_ppm - 800)
        eta_co2 = max(0, 1 - co2_excess / 600)  # Penalty above 800 ppm

        rh = self.humidity_sensor.latest().get("relative_humidity", 50)
        if 30 <= rh <= 60:
            eta_rh = 1.0
        else:
            eta_rh = max(0, 1 - abs(rh - 45) / 30)

        eta_iaq = 0.7 * eta_co2 + 0.3 * eta_rh

        # Weighted combination
        w_C, w_E, w_Q = 0.4, 0.4, 0.2
        cei_value = w_C * eta_comfort + w_E * eta_energy + w_Q * eta_iaq

        self.cei.update(cei_value)

        # Alert on inefficiency
        if cei_value < 0.70:
            Intent.emit("HvacInefficiency",
                       zone_id=self.zone_id,
                       cei=cei_value,
                       comfort_component=eta_comfort,
                       energy_component=eta_energy,
                       iaq_component=eta_iaq)

        return cei_value

    @Sensor.on_data("co2_monitor")
    def monitor_ventilation(self, co2_ppm):
        """Detect inadequate ventilation and trigger outdoor air increase"""
        self.co2_ppm = co2_ppm

        # ASHRAE 62.1: 1000 ppm is typical upper limit for acceptable IAQ
        if co2_ppm > 1000 and self.is_occupied:
            severity = "CRITICAL" if co2_ppm > 1500 else "WARNING"

            self.ventilation_deficit.emit(
                zone_id=self.zone_id,
                co2_ppm=co2_ppm,
                threshold=1000,
                occupancy_count=self.current_occupancy,
                severity=severity,
                action="INCREASE_OUTDOOR_AIR_DAMPER"
            )

        self.estimate_occupancy()  # CO₂ is occupancy indicator
        self.calculate_cei()

    @Sensor.on_data("thermostat")
    def monitor_temperature(self, temp_c, setpoint_c):
        """Track zone temperature and thermal comfort"""
        self.temperature_c = temp_c
        self.setpoint_c = setpoint_c

        self.calculate_pmv()
        self.calculate_cei()

    @Sensor.on_data("vav_controller")
    def monitor_hvac_power(self, airflow_cfm, reheat_kw, fan_power_kw):
        """Track HVAC energy consumption"""
        self.hvac_power_kw = reheat_kw + fan_power_kw
        self.calculate_cei()

    @Sensor.on_data("weather_station")
    def evaluate_economizer(self, outdoor_temp_c, outdoor_humidity):
        """Detect free cooling opportunities"""
        indoor_temp = self.temperature_c

        # Economizer opportunity: outdoor air cooler than indoor + within humidity range
        if (outdoor_temp_c < indoor_temp - 2 and
            outdoor_temp_c > 10 and  # Not too cold (>50°F)
            30 < outdoor_humidity < 70 and  # Acceptable moisture
            self.is_occupied):

            potential_savings_kw = self.hvac_power_kw * 0.3  # Est. 30% savings

            self.economizer_opportunity.emit(
                zone_id=self.zone_id,
                outdoor_temp=outdoor_temp_c,
                indoor_temp=indoor_temp,
                potential_savings_kw=potential_savings_kw,
                action="INCREASE_OUTDOOR_AIR_FOR_FREE_COOLING"
            )

    def predict_occupancy(self, lookahead_minutes=60):
        """Predictive occupancy for pre-conditioning (simplified)"""
        # In real implementation: integrate with calendar APIs, ML models
        # For now: simple heuristic based on time of day
        current_hour = datetime.now().hour

        # Office building pattern
        if 7 <= current_hour < 9:  # Morning arrival
            return int(self.design_occupancy * 0.8)
        elif 12 <= current_hour < 13:  # Lunch exodus
            return int(self.design_occupancy * 0.3)
        elif 17 <= current_hour < 19:  # Evening departure
            return int(self.design_occupancy * 0.2)
        else:
            return self.current_occupancy

# Example instantiation for 500 m² office zone
office_zone = BuildingZone(
    zone_id="BLDG_A_FLOOR_3_WEST",
    area_m2=500,
    design_occupancy=50
)

A.8.5 Visualization: Occupancy-Driven HVAC Optimization

Figure A.8 presents a comprehensive 24-hour HVAC optimization scenario for a commercial office zone. The visualization integrates four critical dimensions: occupancy pattern tracking from multi-modal sensor fusion, temperature control showing setpoint modulation responsive to occupancy state, HVAC energy consumption demonstrating demand-responsive load reduction, and the derived Comfort Efficiency Index (CEI). The annotated timeline shows how predictive pre-conditioning begins at 7:00 AM before occupant arrival, aggressive setback during the lunch vacancy period (12:00–13:00), and evening load shedding after 18:00 departure, achieving 30% energy savings compared to static schedule-based control while maintaining superior thermal comfort.

Occupancy-Driven HVAC Optimization - 24 Hour Office Workday Multi-Modal Occupancy Tracking (Person Count) 50 40 20 0 0:00 6:00 9:00 12:00 15:00 18:00 24:00 Pre-conditioning Morning arrival Lunch exodus Evening departure Dynamic Temperature Control (°C) Comfort (21-23°C) 25 23 22 21 20 18 17 0:00 6:00 9:00 12:00 15:00 18:00 24:00 Setpoint (dynamic) Actual temp Pre-cool ramp Lunch setback Night setback HVAC Energy Consumption (kW) 20 15 10 5 0 0:00 6:00 9:00 12:00 15:00 18:00 24:00 8 kW saved (60% reduction) Legacy schedule (260 kWh/day) Optimized occupancy-driven (180 kWh/day) Daily savings: 80 kWh (31%) Comfort Efficiency Index (CEI) - Composite Score Optimal (>0.85) Acceptable (0.7-0.85) Poor (<0.7) 1.0 0.85 0.7 0.0 0:00 6:00 9:00 12:00 15:00 18:00 24:00 CEI = 0.92 0.72 (lunch setback) Maintains optimal CEI (>0.85) for 18 hours while reducing energy 31% Occupancy-driven optimization achieves 20-35% energy savings while improving thermal comfort

Figure A.8: Integrated occupancy-driven HVAC optimization for a 500 m² office zone (50-person capacity) over a typical workday. Panel 1: Multi-modal occupancy tracking fusing PIR motion sensors, badge access records, and CO₂-based estimates. Morning arrival surge (7:30–9:00) reaches 85% capacity, lunch exodus drops to 20%, afternoon plateau maintains 70–75%, and evening departure clears zone by 18:30. Confidence bands show sensor fusion uncertainty. Panel 2: Dynamic temperature control with occupancy-responsive setpoint modulation. Pre-conditioning begins at 6:45 AM (45 min before arrival) ramping from night setback (18°C) to comfort target (22°C). Aggressive setback during lunch vacancy (20°C) and evening unoccupied period (17°C) reduce HVAC load. Actual zone temperature (solid line) tracks setpoint with <1°C deviation, maintaining PMV within ±0.5 (ASHRAE 55 comfort range). Panel 3: HVAC energy consumption comparing occupancy-driven optimization (blue) to legacy schedule-based control (dashed gray). Peak demand reduction during vacant periods: lunch setback saves 8 kW (60% reduction), evening shutdown saves 12 kW (80% reduction). Cumulative daily energy: 180 kWh (optimized) vs. 260 kWh (baseline), representing 31% savings. Panel 4: Comfort Efficiency Index (CEI) composite score balancing thermal comfort (PMV-based), energy efficiency, and indoor air quality (CO₂, humidity). Morning pre-conditioning maintains CEI >0.85 despite energy ramp. Lunch period shows brief CEI dip (0.72) during aggressive setback for unoccupied space. Afternoon steady-state achieves optimal CEI 0.88–0.92. System demonstrates 30% energy savings while improving average thermal comfort (PMV σ reduced from 0.8 to 0.4) compared to static scheduling.

A.8.6 Deployment Impact

Building operators using Spaxiom-based occupancy-driven HVAC optimization have demonstrated:

  • Energy cost reduction: 20–35% decrease in HVAC energy consumption through occupancy-responsive conditioning and elimination of ghost load (conditioning vacant spaces)
  • Thermal comfort improvement: 40–50% reduction in occupant thermal comfort complaints through predictive pre-conditioning and real-time PMV-based control
  • Ventilation optimization: 15–25% reduction in over-ventilation waste while maintaining ASHRAE 62.1 compliance through CO₂-based demand-controlled ventilation
  • Demand response participation: 10–20% peak demand reduction during utility curtailment events through pre-cooling thermal mass and intelligent load shedding without occupant impact
  • Maintenance cost reduction: 15–25% decrease in HVAC equipment maintenance through reduced runtime hours and optimized cycling patterns (fewer start/stop cycles)

The CEI metric provides a holistic performance indicator that bridges facility management (energy cost reduction), occupant experience (thermal comfort), and regulatory compliance (IAQ standards). By exposing actionable events like PreConditioningRequired, ZoneVacant, and EconomizerOpportunity, Spaxiom enables closed-loop HVAC orchestration that adapts in real time to building usage patterns. Integration with calendar systems (Outlook, Google Workspace) enables predictive conditioning based on scheduled meetings, while machine learning models trained on historical occupancy patterns forecast arrival/departure trends for proactive thermal management. This transforms buildings from reactive, schedule-driven HVAC operation to predictive, human-centric climate control that minimizes energy waste while maximizing occupant comfort and productivity.