Life Community Church Support Documentation

How We Automated Church HVAC with Planning Center and Honeywell

This is the story and support guide for the webhook box we built: why we put it on Proxmox, how Planning Center events drive Honeywell schedules, what went sideways, and the rules that keep the system safe for church staff.

Current production surface: home.buckeyemanor.com/webhooks · App path: /opt/church-webhook · Service: church-webhook

Written from my point of view: I wanted this system to feel simple for the church staff: approve the right events in Planning Center, attach the right HVAC resources, and let the building take care of itself. Under the hood, though, that meant building a small reliable integration layer between Planning Center Calendar and Honeywell Total Connect Comfort — two systems that were not exactly begging to be best friends.

Why we built a Proxmox webhook box

The church already had great source data in Planning Center Calendar. Approved events had times, rooms, resources, and real operational intent. The manual problem was that HVAC still depended on humans remembering to translate that schedule into thermostat changes. That is fine when there are only a few predictable weekly patterns. It gets messy when meetings, rehearsals, group nights, youth events, Sunday services, special events, and building exceptions move around.

The goal was not to make a flashy app. The goal was to remove a repetitive operational chore and reduce the chance that a room is freezing, roasting, or running HVAC all week because somebody forgot to undo a temporary adjustment.

I built this as a dedicated webhook/integration service on the church infrastructure instead of burying it inside a personal laptop, a random cloud script, or a fragile one-off automation. The Proxmox box gives us:

Architecture diagram

Planning CenterApproved calendar eventsHVAC resources like HVAC 10 WebhookLCC on Proxmox/opt/church-webhookExpress + Python venvsystemd service + timersdisk caches + state files Caddy Reverse Proxyhome.buckeyemanor.com/webhooksTLS + public routes HVAC Sync Scriptpco-hvac-sync.pyfilters HFP, maps zoneswrites schedules only Honeywell HomeEditScheduledPeriodSendSchedulevisible app schedules Support UI/honeywell/honeywell-bulk/honeywell-fan Local State + Cachesdisplay plan cache · Honeywell occupied-window cache · bulk temp overrides · fan state

How the automation works

The automation starts with Planning Center Calendar because that is where the church already decides what is real. The important rule is that the automation should only care about approved calendar events that have HVAC resources attached. If a room reservation never asked for HVAC, the system should not guess.

Input

Approved PCO events with HVAC resources such as HVAC 01, HVAC 10, or paired zones like HVAC 05/06.

Output

Visible Honeywell schedule periods for the rolling 7-day Honeywell window. Not live holds. Not temporary manual setpoints.

The sync script pulls upcoming approved PCO event instances, deduplicates the HVAC resource requests, maps them to thermostat IDs, applies pairing rules, filters ignored zones, and builds a plan. The UI then shows that plan in a support-friendly way.

The key mapping is simple on purpose: PCO resource names include the HVAC number, and that number maps to the Honeywell thermostat number. For example, HVAC 10 maps to 10: Office.

Why we write Honeywell schedules instead of setpoints

This was the biggest gotcha. The easy thing to do with Honeywell is to set the thermostat target temperature directly. The problem is that direct setpoint or hold writes do not reliably update the schedule that staff see in the Honeywell app. That creates a support nightmare: the automation may think it changed something, but the visible app schedule still tells a different story.

Rule: automation must write Honeywell visible schedules, not live setpoint holds.

The Honeywell schedule path we ended up using is based on portal endpoints:

GET /portal/Device/Menu/EditScheduledPeriod/<deviceId>?period=<day>_<periodType> POST /portal/Device/Menu/EditScheduledPeriod/<deviceId> POST /portal/Device/Menu/SendSchedule?deviceId=<deviceId>

That gives us changes that show up where staff expect to see them: in the actual Honeywell schedule.

We also learned that Honeywell is realistically a rolling 7-day schedule target. The support page can display what PCO says is coming, but writes should stay inside the next 7 days.

Support pages we added

/honeywell — Schedule view

This page shows each managed thermostat as a tab and displays a rolling 7-day schedule starting with today. The event cards intentionally show PCO event names because Honeywell itself only shows schedule periods, not the names of church events.

Each event now shows two pieces of context:

/honeywell-bulk — Bulk temperature update

This lets support select multiple rooms and update occupied heat/cool values across the rolling schedule window. It still writes schedules only. It does not create live holds.

Warehouse thermostats 11 and 12 are heat-only. They show 50° Heat and Heat only, and the UI should not show or write a cooling setpoint for them.

/honeywell-fan — Bulk fan update

This page controls whether occupied schedule periods run the fan in continuous mode or auto mode. Known continuous fan rooms were seeded as 05, 06, and 10. This is useful for airflow during occupied windows without creating live fan holds.

/pco-hvac-status — Operational status

This page is the support window into the automation. It is where we can confirm what the service thinks it should do, whether the sync has run, and what the automation is seeing from PCO.

Gotchas we learned the hard way

PCO rate limits are real. The page originally tried to refresh live PCO data too often. PCO can throttle around 100 requests per 20 seconds. We added disk-backed cache and cooldown behavior so browser refreshes do not hammer the API.
UTC will betray you. A schedule page built from UTC midnight showed yesterday as the first row. We changed the schedule to start from today in Eastern time.
Honeywell does not show PCO event names. Honeywell shows schedule periods. Our support UI shows PCO event names so humans understand why HVAC is being requested.
Covered events should not create duplicate Honeywell rows. If Office is already occupied from 7:00 AM to 6:00 PM, a 1:00 PM staff meeting is covered. It should be visible in our support UI as PCO demand, but it does not need a new Honeywell schedule period.
HFP+ is intentionally ignored. Thermostat 13 exists but is not managed by this automation. We also filter any PCO event/resource/title/owner containing HFP so it does not leak into the schedule view.
Paired zones are paired for a reason. 05/06 and 11/12 must move together. If one side is scheduled, the automation should treat the pair as a unit.

Support operations

Most support starts on the webhook box:

cd /opt/church-webhook node --check app.js systemctl restart church-webhook journalctl -u church-webhook -n 80 --no-pager

Useful HVAC-specific checks:

/opt/church-webhook/venv/bin/python /opt/church-webhook/HVACScripts/pco-hvac-sync.py --verbose /opt/church-webhook/venv/bin/python /opt/church-webhook/HVACScripts/refresh-honeywell-schedule-windows.py curl -sk https://home.buckeyemanor.com/webhooks/honeywell | grep -E "ReferenceError|TypeError|HFP|Covered by|Needs extra" | head -40

Caddy and the public domain

The public domain is routed through Caddy. The important support concept is that home.buckeyemanor.com/webhooks terminates TLS at Caddy and proxies to the Node/Express app on the webhook server. Any new public route needs to exist in Express, and Caddy must continue forwarding the hostname correctly.

During setup we also used a temporary code-drop host for installer scripts. That let us deploy repeatable one-line fixes to the webhook box without pasting huge files by hand.

What manual process this replaced

Before this, HVAC depended on someone noticing approved PCO events, deciding which thermostat applied, checking whether the normal Honeywell schedule already covered it, and then manually changing schedules or setpoints. Now PCO approval/resource data drives a plan automatically. Staff can still review and support it through the web pages, but the boring translation layer is handled by the webhook box.

Bottom line: Planning Center remains the source of truth for church events, Honeywell remains the source of truth for thermostat schedules, and the webhook box is the translator that keeps them from making humans do copy/paste HVAC chores.