Skip to main content
  1. Projects/

Taming the Arizona Heat: SRP Time-of-Use Automation

Status In Progress
Cost $0
Time Spent ~4 hours
Outcome

Automated HVAC load shifting to avoid SRP peak pricing windows

Stack
Home Assistant Node-RED SRP

Living in the Arizona desert, my electricity bill is not just a monthly expense. It is a tactical challenge. With SRP’s Time-of-Use plans, power prices double during peak hours. This post covers how I built a Node-RED logic engine to load shift my cooling, and the problems I ran into along the way.

An Ecobee thermostat mounted on the wall, showing 70°F inside and a 73°F setpoint.
The Ecobee is the endpoint for all of this logic. Every automation in this post ultimately sends a command here.

The Problem
#

In the summer, SRP hits you hard between 2:00 PM and 8:00 PM. If your AC kicks over at 2:05 PM to catch up with a 115°F afternoon, you are paying maximum price for maximum effort. My goal was to stop reacting to the heat and start anticipating it.

The plan was to pre-cool the house by 2 degrees at 1:30 PM, then let the house coast through the peak hours by raising the setpoint.

The Goal
#

A fully automated HVAC scheduler that pre-cools the house before peak pricing starts, coasts through the expensive window, and accounts for season changes, occupancy, and guest overrides without any manual intervention.

The Build
#

The Investigation
#

The first version was simple. A set of time triggers in Node-RED that fired at 1:30 PM and 2:00 PM and sent setpoint commands to the Ecobee via Home Assistant. It worked immediately, which was encouraging.

Then July ended and August arrived. The schedule that worked perfectly in summer was fighting me in the shoulder season, and by December it was completely wrong. Arizona does not just have hot and cold. It has Peak Summer, Winter, and those weird weeks in between. Winter peak hours shift to early morning and evening, almost the opposite of summer.

A second problem emerged around the same time. The automation was pre-cooling an empty house on days when nobody was home. The AC was running hard at 1:30 PM for no reason.

The Pivot
#

Static time nodes were not going to work. The schedule needed to know what month it was and whether anyone was home before sending any commands.

For the season problem I added a JavaScript Season Filter function node in Node-RED. It checks the current month before passing the signal along:

const month = new Date().getMonth();
// 4 = May, 10 = November
if (month >= 4 && month <= 9) {
  return [msg, null]; // Route to Summer Logic
} else {
  return [null, msg]; // Route to Winter Logic
}

The Node-RED function node editor open, showing the Winter WD Filter code on a single line.
Double-clicking any function node opens this editor. The name at the top helps you stay organized once your flow grows.

For the occupancy problem I built a Safety Stack. Before any temperature command reaches the thermostat, it passes through three gatekeeper nodes in sequence:

  1. Vacation Mode: If this is on, all scheduling is bypassed and the thermostat holds a flat 85°F.
  2. Occupancy: Using phone location tracking, if the house is empty the pre-cool step is skipped entirely.
  3. Master Enable: A dashboard toggle to pause the automation when guests want manual control.

A Home Assistant dashboard card showing House Mode States and House Mode Overrides, with toggles for Guest Mode, Vacation Mode, and more.
This card is the control panel for the Safety Stack. If Vacation Mode is on, the Node-RED flow stops before it ever touches the thermostat.

The Fix
#

After a few iterations the Summer weekday schedule settled into this:

TimeActionSetpointWhy
1:30 PMPre-Cool76°FStore cold while power is cheap
2:00 PMLoad Shed80°FCoast through the peak window
8:00 PMRecover78°FReturn to comfort once rates drop

The complete flow from start to finish. The blue group is the Winter schedule, the pink group is the Summer schedule, and everything funnels into the Safety Stack before the final thermostat call:

The complete Node-RED flow showing Winter and Summer schedule groups on the left, feeding into the Safety Stack and Apply Temperature node on the right.
Each colored group is independent. Nothing in the Summer group affects the Winter group.

The final node is the Apply Temperature action node, which is the only node that actually talks to the thermostat:

The Node-RED action node editor showing the climate.set_temperature action targeting the Thermostat entity, with a JSON data field containing the payload temperature.
The {"temperature": {{payload}} } in the Data field takes whatever setpoint the flow calculated and sends it to the thermostat. This one node is reused by every schedule branch.

Keep your checks in this order when building something similar:

[Time Trigger] -> [Season Filter] -> [Weekday/Weekend Check] -> [Occupancy Check] -> [Thermostat Service Call]

Each node is a gate. If any check fails, the message stops there and the thermostat is left alone.

Results
#

By shifting the heavy cooling work to the hour before the peak window opens, daily on-peak demand has flattened noticeably. The AC barely runs between 3:00 PM and 6:00 PM because the thermal mass of the house was already brought down during the pre-cool phase.

This is still marked as a work in progress because the winter schedule has not been through a full season yet and I expect it will need tuning.

What I Would Do Differently
#

I would build the season filter and the Safety Stack before doing anything else instead of adding them after the fact. Starting with just the time triggers felt like a quick win but it meant reworking the flow structure twice. The Safety Stack especially should be the first thing you build because every other node in the flow depends on it.

What Is Next
#

I am looking into pulling SRP pricing data directly via an API. The goal is to have the house adjust automatically if SRP ever changes their peak windows, making the whole system truly set and forget.

If you want to build this yourself, I wrote a full step-by-step tutorial that walks through every node, explains the logic, and includes the complete flow as a downloadable JSON file:

Dynamic HVAC Scheduling with Node-RED and Home Assistant