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:
- A stable always-on place to run church integrations. The webhook server can keep timers, caches, logs, and local state.
- Clean network ownership. The service lives where the church services live, not on somebody’s personal machine.
- Easy backup and rollback. Before edits, we keep a rolling backup like
app.js.backup-current. - Service-level visibility. systemd can restart the app, journalctl can inspect logs, and support does not depend on a browser tab being left open.
- Room for future integrations. The same pattern can handle other webhook-style jobs later without mixing unrelated systems.
Architecture diagram
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.
The Honeywell schedule path we ended up using is based on portal endpoints:
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:
- PCO event — this came from Planning Center demand.
- Covered by Occupied 1/2 — the event fits inside the existing Honeywell occupied schedule.
- Needs Extra Schedule — the event falls outside the normal occupied window and needs an extra schedule period.
/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
Support operations
Most support starts on the webhook box:
Useful HVAC-specific checks:
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.