Bringing BACnet HVAC Into Home Assistant With an ESP32
Inside pw-esp-bacnet-proxy, an open-source project that connects existing Delta heating and cooling controls to a locally managed smart home.
Summary
pw-esp-bacnet-proxy connects Delta BACnet/IP heating and cooling controllers to Home Assistant through MQTT. Its retained ESP32-WROOM-32D configuration uses a WIZnet W5500 as the controller-facing SPI Ethernet interface, while ESP32 Wi-Fi provides home-network connectivity. This W5500 configuration is now a legacy/recovery profile; the project’s primary T-ETH-Lite configuration uses an RTL8201 Ethernet PHY instead.
What the Project Does
Developed by Piers Wingfield, the project makes an existing Delta DAC-1180E HVAC installation accessible through Home Assistant and a local web dashboard. Rather than replacing the HVAC controller, the ESP32 reads its BACnet objects and issues control writes. Home Assistant receives climate entities through MQTT discovery.
In the W5500 configuration, the communication path is:
Delta HVAC controller ⇄ Ethernet ⇄ W5500 ⇄ SPI ⇄ ESP32 application ⇄ Wi-Fi ⇄ MQTT broker ⇄ Home Assistant
A browser communicates separately with the ESP32’s HTTP server for configuration, monitoring, and control. Ethernet serves the controller network; Wi-Fi serves the home network. The firmware exchanges application data between these interfaces rather than requiring Home Assistant to speak BACnet directly.
The bridge operates as a BACnet client, reading and writing the Delta panel’s objects. It is not a general-purpose BACnet server, and its component documentation excludes BBMD functionality used for BACnet broadcast distribution across IP networks. The repository records a successful device-name read over the physical W5500 connection, confirming that WIZnet usage extends beyond a proposed wiring diagram.
Where WIZnet Fits
The W5500 supplies the wired controller interface
The W5500 provides an Ethernet MAC, PHY, and packet-buffer memory accessible over SPI. In this project, that hardware supplies the physical Ethernet connection to the HVAC controller. The ESP32 remains responsible for BACnet processing, room-state handling, MQTT communication, and the web interface.
The practical advantage of this arrangement is that a separate Ethernet module can be connected to the ESP32 development board through SPI, leaving Wi-Fi available for the home network. The retained profile defines the SPI signals, interrupt, reset, and operating clock explicitly.
Hardware TCP/IP capability is not the same as its use here
This implementation should not be described as a W5500 hardware TCP/IP-offload application.
Although the W5500 supports a hardwired TCP/IP stack, Espressif’s W5500 driver documentation states that its driver does not use that stack. The project creates Espressif Ethernet-driver instances and implements BACnet/IP through ESP32 lwIP UDP sockets. The W5500 therefore supplies Ethernet access, while the software networking stack remains on the ESP32.
Consequently, the presence of a W5500 is not evidence of reduced TCP/IP processing load or eliminated networking RAM requirements. Those benefits would require a different integration using the chip’s hardware socket interface.
The current primary board is a separate implementation
The T-ETH-Lite profile uses an ESP32-WROVER-E with an integrated RTL8201 RMII PHY, 16 MiB flash, and 8 MiB PSRAM. It does not require an external W5500. The repository retains the W5500 configuration as a separate legacy/recovery build, so its wiring and firmware settings must remain distinct from the primary board.
Implementation Notes
Creating the W5500 Ethernet driver
File: firmware/bacnet_bridge/components/ethernet_init/ethernet_init.c
Lines: 221–225 in the reviewed source.
eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(CONFIG_EXAMPLE_ETH_SPI_HOST, &spi_devcfg);
w5500_config.int_gpio_num = spi_eth_module_config->int_gpio;
w5500_config.poll_period_ms = spi_eth_module_config->polling_ms;
esp_eth_mac_t *mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config);
esp_eth_phy_t *phy = esp_eth_phy_new_w5500(&phy_config);This excerpt creates the W5500-specific MAC and PHY driver instances, using the selected SPI device and interrupt or polling configuration. The surrounding function installs those instances through ESP-IDF’s Ethernet driver. It establishes the hardware-facing Ethernet interface rather than opening W5500 hardware TCP or UDP sockets.
Connecting Ethernet to the software network stack
File: firmware/bacnet_bridge/main/main.c
Lines: 1421–1425 in the reviewed source.
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH();
EthNetif = esp_netif_new(&cfg);
esp_eth_netif_glue_handle_t glue = esp_eth_new_netif_glue(eth_handles[0]);
ESP_ERROR_CHECK(esp_netif_attach(EthNetif, glue));
ESP_ERROR_CHECK(esp_netif_dhcpc_stop(EthNetif));The application creates an Ethernet network interface, attaches the driver, and stops its DHCP client before applying the controller-side static IP configuration. This is the connection between the Ethernet driver and the ESP32 networking environment.
The BACnet transport resides in firmware/bacnet_bridge/components/bacnet_client/bacnet/datalink/bip_socket_esp_idf.c. It creates a UDP socket and attempts to bind it to the supplied Ethernet interface using SO_BINDTODEVICE. That distinction matters because the ESP32 also has a Wi-Fi interface. A failed device binding is logged as a warning, so commissioning should confirm the successful binding message rather than assume interface selection succeeded.
Reducing unnecessary controller traffic
The application includes a 64-entry BACnet read cache with a 30-second lifetime and invalidates the relevant cached value after a successful write. This reduces repeated Ethernet transactions, but a cached response is not necessarily a fresh controller measurement. The cache is application behavior on the ESP32, not W5500 hardware functionality.
Practical Tips / Pitfalls
- Select the W5500 build explicitly. Use
sdkconfig.defaults;sdkconfig.w5500.defaultswith a separate build and configuration directory. The default build targets T-ETH-Lite, whose Ethernet interface and memory configuration differ. - Check interrupt and reset wiring as well as SPI. The W5500 profile assigns interrupt to GPIO4 and reset to GPIO16. The architecture notes associate a missing actively controlled reset with intermittent initialization failures after software restarts.
- Verify controller discovery and writable objects. The tested Delta panel does not answer broadcast discovery, so the bridge uses targeted discovery. Confirm the actual controller and object mappings before enabling automated writes.
- Test Wi-Fi while Ethernet is active. The project’s diagnostic record reports degraded Wi-Fi during W5500 BACnet traffic on the tested assembly. Compare idle and loaded operation when evaluating module placement, cabling, and power changes; this is an installation-specific finding, not a universal W5500 defect.
- Distinguish dashboard access from working BACnet. After repeated Ethernet initialization failures, the firmware can remain reachable over Wi-Fi while reporting BACnet as unavailable. A responsive web page alone does not establish that HVAC communication works.
- Check memory headroom during commissioning. Use
/api/debug/stacksto inspect the largest free memory block and task-stack headroom. Retain the matching firmware ELF file for crash diagnosis; a successful flash is not an endurance test.
FAQ
Why is the W5500 suitable for this ESP32 configuration?
Its SPI interface provides a practical way to add wired Ethernet to the ESP32 development board while retaining Wi-Fi for home-network access. In this implementation, the justification is Ethernet connectivity and driver integration—not demonstrated hardware TCP/IP offloading.
How does the W5500 connect to the ESP32?
The retained profile assigns MOSI to GPIO23, MISO to GPIO19, SCLK to GPIO18, chip select to GPIO5, interrupt to GPIO4, and reset to GPIO16. It configures a 12 MHz SPI clock. Power input must match the specific breakout module’s rating.
What does the W5500 do in this project?
It carries controller-facing Ethernet traffic for BACnet/IP reads and writes. The ESP32 interprets BACnet data and translates application state and commands into MQTT communication; the W5500 itself does not interpret HVAC objects or communicate directly with Home Assistant.
Can a beginner build the W5500 version?
It is better suited to someone comfortable with ESP-IDF builds, GPIO wiring, IP configuration, and MQTT. The setup wizard helps with configuration, but access to a compatible HVAC controller and verification of its control objects remain essential. A running MQTT broker is required for Home Assistant integration.
How does the W5500 version compare with the RTL8201 alternative?
The W5500 version uses an external SPI Ethernet module. The primary T-ETH-Lite board instead connects its RTL8201 PHY to the ESP32’s internal Ethernet MAC through RMII and provides additional flash and PSRAM. Both retain the project’s BACnet/MQTT application design; they are alternative hardware profiles, not components intended to operate together.
