I’ve got a Cairox / France Air Volcane XS 250 heat-recovery ventilation unit, and I wanted proper local control from Home Assistant instead of relying on the stock wall panel. Here’s how it went, and what came out of it.
The rabbit hole
The unit talks Modbus over an RS-485 link, so in theory this should’ve been straightforward. In practice, the manual I got from support was thin and, in a few places, just wrong — e.g. its error-bit table skips a bit position with no explanation, and one section reads as if a couple of registers configure an “alarm interval in days” when they actually don’t do that at all.
So I ended up doing what you’d expect: hooked up a USB-RS485 adapter, ran mbpoll directly against the unit, and went register by register — cross-checking readings against the LCD panel and the board’s silkscreen/diagram, flipping settings and watching what changed, and even measuring power draw at each fan-speed code with the two motors isolated, just to be sure which codes were real speeds and which weren’t documented at all. Some registers only respond to reads (function code 03, holding registers), one register is write-only and never answers a read, that kind of thing — nothing you’d get from the manual alone.
First pass: plain YAML
Once I trusted the register map, the fastest way to get something working was the classic Modbus YAML platform — a modbus: hub, a handful of input_number/input_select helpers, and some scripts wired to the registers. It worked, but it’s clunky: no native number/select entities, nothing UI-configurable, and no clean way to represent a write-only register without hacks.
Turning it into a real integration
So I decided to build an actual custom integration instead — config flow, typed entities, the works. I built it with Claude’s help, leaning on the new modbus-connection library that shipped with HA 2026.9, which lets you describe the register map as typed fields on a class instead of hand-rolling raw Modbus calls. Claude was particularly useful for working through some of the gnarlier design questions — like how to model a register that’s write-only with no read-back, when the library’s normal pattern assumes fields you can both read and write.
What it does
Fully configurable from the UI (no YAML), with native number and select entities for controls the classic Modbus YAML platform can’t express:
- Return / outdoor / exhaust / supply air temperature sensors
- Operating hours sensor
- Boost active, fire alarm, bypass active, defrost active binary sensors
- 8 error-flag binary sensors (sensors, EEPROM, filter, fans)
- Power on/off switch
- Exhaust fan speed select (Off / Speed 1 / 2 / 3, live readback)
- Supply fan speed select (Off / Speed 1 / 2 / 3, write-only — the unit never answers a read on this register, confirmed by testing)
- Bypass minimum temperature and range numbers
- Clear filter alarm / clear weekly timer buttons
Requirements
- Home Assistant 2026.9.0+
- Network access to the unit’s Modbus TCP interface (a small RS-485-to-WiFi gateway like the Elfin EW11 works well — wiring notes are in the README)
Installation
Custom repository via HACS for now (https://github.com/zbuh/ha-volcane-xs, category Integration) — submission to the default store is in review.
Known limitations
- Supply fan speed has no readback (hardware limitation of this variant, not the integration).
- Only temperature, ventilation and bypass sub-systems are covered — my unit has no CO2/humidity sensor or electric heater installed, so those registers exist on other hardware variants but aren’t implemented here.
Feedback, bug reports and PRs welcome on GitHub. If you’ve got a Volcane XS variant with CO2/humidity/heater and want to help extend the register map, I’d love the help.