The geek page

This is the page I wish existed when I was wiring up my own van. The kit page covers the stuff in normal English. This page is for people who already know what a Zigbee coordinator is and want to see what actually runs in my van. Home Assistant OS on a Pi, a Cerbo GX, ZHA with Sonoff sensors, a three-layer fridge thermal loop, and a five-view kiosk dashboard that lives on a rugged Samsung tablet bolted to the habitation wall.

Got a Home Assistant question?

Ask the HA Expert. Rooted in the official HA docs. ZHA, Cerbo over MQTT/Modbus, Fully Kiosk, automations, the lot. One question at a time.

The stack at a glance

Host
Pi 4 (8 GB)
HAOS 17.2
Storage
256 GB SSD over USB3
Zigbee
Sonoff ZBDongle-E
ZHA (TI CC2652)
Power
Victron MultiPlus II
Cerbo GX, LiFePO4
Network
GL-iNet X2000
192.168.1.0/24
Kiosk
Samsung Tab Active4 Pro
Fully Kiosk Browser
Remote
Tailscale + Cloudflare Tunnel
Backups
Snapshot nightly
Google Drive weekly

The hardware

Raspberry Pi 4 (8 GB), fanless case, 256 GB SSD over USB3

Home Assistant OS, not Supervised. I went back and forth on this. HAOS gives you the appliance experience with the Supervisor and add-ons (MQTT broker, File editor, HACS, Terminal) all one-click, and that is what I ended up wanting. Supervised lets you run other Docker workloads on the host, but I already have an Unraid box at home for that and a second NUC for heavier lifting. The Pi should do one thing and be restorable in ten minutes if it dies. HAOS gets out of the way.

SSD rather than SD card is non-negotiable if you care about the thing surviving a year. SD cards and a write-heavy recorder database are a losing fight, and an appliance install writes constantly.

Sonoff Zigbee 3.0 USB Dongle Plus (ZBDongle-E)

Paired with ZHA, not Zigbee2MQTT. ZHA lives inside HA, one fewer moving part, and the Dreo / Victron / MQTT add-ons already give me plenty of other integrations to maintain. Mounted on a USB3 extension cable so it is not squeezed against the Pi's own Wi-Fi radio. Range across a motorhome is fine from a single coordinator; no routers needed at this distance.

The Zigbee fleet (what is actually paired)

Tuya, Sonoff, and eWeLink. No Aqara, I went off them after a couple of battery surprises on door sensors. Current devices:

Home Assistant to Cerbo: how the power stack actually talks

Not MQTT. Modbus TCP.

The Cerbo GX will happily publish over MQTT and that is the integration most guides point you at. I started there and swapped. The LaggAt ha-victron HACS integration connects over Modbus TCP on port 502, the Cerbo's native protocol, and gives you every vebus, solarcharger, system and ESS register as a typed HA entity. 268 sensors for my install, all with proper units and device classes, no YAML topic-juggling.

MQTT is still running on the Pi as a Mosquitto add-on. I use it for a couple of other things. But the Cerbo connection is not one of them.

The MultiPlus mode decision: CHARGER vs ON

This is the bit that took me the longest to think about and the bit most motorhome Home Assistant writeups get wrong.

The MultiPlus has three modes: OFF, CHARGER, and ON. Most guides assume you want ON permanently so that Power Assist is available. Power Assist is Victron's trick where the inverter tops up shore power from battery whenever your AC load exceeds the current limit you told the Cerbo the pillar could supply, so you do not trip a 6A campsite breaker with a kettle and a fridge running at the same time.

My van runs in CHARGER mode as the default. Reasons:

What I do have instead is a Shore Power Breaker Alert automation that pings my phone when AC consumption crosses 2100W, roughly 9.1A at 230V, just under a typical 10A pillar limit. That is the "back off the kettle" warning. It is a substitute for Power Assist that puts a human in the loop, which is what I actually want because I am the one deciding between kettle and microwave on a 6A site.

When I want Power Assist, the kiosk has a tile that flips the mode. CHARGER is blue and says "Tap to Power Up". ON turns it green and reads "230V Sockets LIVE - Tap for Safe Mode". One touch in each direction. ESS is already configured in self-consumption mode, so when the MultiPlus goes to ON, the right behaviours come with it.

# The conditional tile on the Pilot view, verbatim from my dashboard
type: conditional
conditions:
  - entity: select.victron_vebus_mode_227
    state_not: 'ON'
card:
  type: custom:mushroom-template-card
  primary: Charger Only
  secondary: Tap to Power Up
  icon: mdi:battery-charging
  icon_color: blue
  tap_action:
    action: call-service
    service: select.select_option
    target:
      entity_id: select.victron_vebus_mode_227
    data:
      option: 'ON'

The fridge thermal loop

Why it matters on a retrofit

OEM motorhomes get a factory fridge chimney: a dedicated vent bay with a top and a side grill, sized for the fridge model. Retrofits do not. You stuff a compressor fridge into a kitchen cupboard and the cupboard cooks unless you help it. Home Assistant gives me a smarter version of the chimney: a differential thermostat, a hysteresis loop, and a battery-aware safety gate.

The vent itself

A plate vent on the side wall holds three 12V fans: two exhaust, one intake. The asymmetric ratio gives slight negative pressure in the cupboard, so any small leaks in the cupboard wall pull into the cupboard and out through the vent rather than pushing warm compressor air into the habitation. A Zigbee relay (a Tuya TS0503B presenting as a "light" to HA, which is mildly funny because it is a 12V fan circuit) switches the fans on and off.

The automation

Three layers of monitoring, one actuator:

The active cooling loop also has a battery safety gate: fans will not run if leisure state-of-charge is below 30%. The fridge cupboard bleeding a few degrees to the habitation is a much smaller problem than running a set of fans flat for an hour and ending up at 15% SoC overnight.

# The real automation, exported from HA
alias: "Climate - Fridge Vent Differential"
description: "Only run fans if air behind fridge is significantly hotter than cabin air."
triggers:
  - entity_id: sensor.fridge_rear_temperature
    trigger: state
conditions:
  - condition: numeric_state
    entity_id: sensor.victron_system_battery_soc
    above: 30
actions:
  - choose:
      - conditions:
          - condition: template
            value_template: "{{ (states('sensor.fridge_rear_temperature')|float - states('sensor.sonoff_snzb_02d_temperature')|float) > 8 }}"
        sequence:
          - action: switch.turn_on
            target: { entity_id: switch.fridge_vent_fans }
      - conditions:
          - condition: template
            value_template: "{{ (states('sensor.fridge_rear_temperature')|float - states('sensor.sonoff_snzb_02d_temperature')|float) < 4 }}"
        sequence:
          - action: switch.turn_off
            target: { entity_id: switch.fridge_vent_fans }

The inverter cupboard gets the same treatment with a separate temperature sensor and a separate relay. The principle is identical; the thresholds are different because the inverter only cares when it is actually running.

The other automations worth calling out

Heater (Dreo) with a three-layer safety interlock

The Dreo Atom One S electric heater lives in the habitation. It only runs if all three of these are true:

If L1 drops below 100V (shore power pulled, pillar tripped, extension cable snagged) the heater cuts immediately. The point is not "polite shutdown". The point is that a 2kW heater quietly switching from shore to inverter is how you wake up at 4am to a flat battery and a pissed-off LiFePO4 BMS.

Shore power breaker alerts

Two automations, opposite directions:

Low battery alert

SoC below 20% pings phone and tablet. Simple. Paired with the 30% fridge-fan gate so that by the time the battery alert fires, the active-cooling loop is already off.

Auto lights on presence

SNZB-06P presence plus its own illumination sensor. Lights on when someone walks in and the ambient is dark. Off 5 minutes after the van goes empty. The sensitivity is set to low so a sleeping person turning over does not wake the strip lights up at 3am.

Home zone follows the van

One of the most useful, quiet automations. The tablet runs the HA Companion app with high-accuracy GPS. A trigger on the tablet's location updates HA's zone.home to wherever the tablet currently is, every ten minutes. The van is the home zone. Arrive at a new aire, the home zone moves to that aire. All the presence and not-home logic keeps working correctly without manual intervention.

alias: "The Dusty Van: Update Location"
description: "Moves the Home zone to the tablet's GPS coordinates"
triggers:
  - entity_id: device_tracker.sm_t636b
    trigger: state
actions:
  - action: homeassistant.set_location
    data:
      latitude: "{{ state_attr('device_tracker.sm_t636b','latitude') }}"
      longitude: "{{ state_attr('device_tracker.sm_t636b','longitude') }}"

The kiosk dashboard

A Samsung Galaxy Tab Active4 Pro (SM-T636B, the ruggedised one) is bolted to the habitation wall, running Fully Kiosk Browser pointed at a dedicated Lovelace dashboard. Five views, each in full-screen panel mode so you can tap once and land anywhere in the stack.

The dashboard is built on two HACS components:

Pilot view: the one you land on

Ten numbered pins on the image. Tap a pin or a card below to highlight the match.

Annotated Pilot view of the Dusty Van kiosk dashboard
1
Chip bar: glanceable status
Four mushroom-chips: inside temp, outside temp, battery time-to-go, and a sunrise/sunset tile that changes background from blue night to orange sunset depending on sun.sun state. The time-to-go chip says "Stable" if the battery is not discharging and otherwise shows hours remaining.
2
All Systems Off / Tap to Kill
Master kill. One tap turns off strip lights + heater together. The primary text changes to "System Active - Tap to Kill" in red if either is on, or "All Systems Off" in green if both are off. Bedtime button.
3
MultiPlus mode switcher
Conditional card on select.victron_vebus_mode_227. "Charger Only - Tap to Power Up" (blue) when parked at home. Tap flips to ON mode, enabling 230V sockets + Power Assist + ESS self-consumption. Tap again on "Sockets LIVE" to go back to CHARGER.
4
Main Lights
Mushroom light card with brightness slider. Controls the Tuya TS0503B strip-light dimmer (light.tz3210_f0byevky_ts0503b). Swipe for brightness, tap icon to toggle.
5
Total AC Load
Live wattage through the MultiPlus AC-out. When this climbs past 2100W the Shore Power Breaker automation fires a notification warning you are within 10% of a typical 10A pillar trip limit. Watch this tile when you put the kettle on.
6
Battery / Solar / Shore tiles
Three-tile strip pulling from the Victron integration. Battery SoC percentage, Solar production in watts, Shore power draw in watts. These are the three numbers you want to see at a glance before plugging in a kettle.
7
Fridge
Internal fridge temperature plus a "seen X ago" staleness indicator. If the zigbee_fridge_inside_temperature sensor stops reporting, the tile tells you - usually the first clue that the Zigbee mesh has dropped something.
8
Heater
Dreo Atom One S heater tile. Tap to toggle. The automation behind it only actually runs the heater if shore power is above 200V and the SNZB-06P presence sensor sees someone in the van - triple safety interlock.
9
Location + weather forecast
Top card geocodes the tablet's GPS into a short address (sensor.sm_t636b_geocoded_location). Below it, a Met.no weather-forecast card centred on "Home" - and Home follows the tablet, so this forecast is always for wherever the van is parked.
10
Lithium Bank gauge
Mushroom gauge with colour segments: red under 25%, amber 25-50%, green above 50%. Primary text reads either "System Stable" or "X hours remaining" depending on whether the bank is actively discharging. Fed by sensor.victron_system_battery_soc and sensor.victron_system_battery_time_to_go.

/dusty-van/pilot - tap a pin or a card to highlight the match.

Energy view: one card does the whole job

power-flow-card-plus takes battery SoC, solar watts, consumption, and grid watts, and draws the canonical Victron four-pole diagram with animated flow dots. It is worth showing to anybody who asks "what's a Cerbo for" because it answers the question in about two seconds. The animated dots below are a CSS approximation of the real card's flow; the real one in the van is reactive to live state.

Energy view showing the power-flow-card-plus diagram

/dusty-van/energy - Flow dots are animated client-side as a CSS approximation. The real card updates with live state every few seconds.

Navigation, Weather, Spotify

Navigation is a map card centred on the tablet's device_tracker, which means it shows the van exactly where it is parked (recall: the Home zone follows the tablet, so "Home" and "where the van is" are the same marker). Weather is a stock weather-forecast card on met.no's forecast for the current location. Spotify is a media-control card on my Spotify Connect account.

Import this dashboard

All the Lovelace config, exported from my Pi today:

Entity names are mine. You will want to rename sensor.victron_system_battery_soc and friends to match your install before you paste.

Network and remote access

The van LAN

The GL-iNet X2000 (Spitz AX) broadcasts "The Dusty Van" 2.4 / 5 GHz plus a guest SSID, with a 4G modem bonded to whichever EU SIM I am on. LAN is 192.168.1.0/24. Everything the Pi controls (tablet, Cerbo, Sonos, Nest Mini, Broadlink, Dreo) sits on that LAN. AirVPN WireGuard clients for UK and Switzerland are configured on the router itself so any device on the van LAN can exit through a specific country if it wants. There is no mystery route: the X2000 is the gateway, every client is on the same /24, and Zigbee is the one thing that does not touch Wi-Fi.

Local Wi-Fi note. Every automation assumes devices are on the same subnet. Do not put the Pi on the guest network. It needs to be on the same /24 as the phones that control it and the Cerbo that feeds it data.

The four ways to reach the van from outside

ApproachProsCons for motorhomes
Tailscale WireGuard under the hood. Works through NAT and CGNAT. Free tier covers a single van. The Pi can advertise 192.168.1.0/24 as a subnet route so any tailnet peer sees the whole van LAN, including the Cerbo web UI. Every device that wants to reach the van needs the Tailscale app installed and signed in. Fine for you. Awkward for a family member who opens the van dashboard twice a year.
Cloudflare Tunnel A real van.tripgen.co.uk URL with a proper TLS cert. No port forwarding. Cloudflare Access sits in front with SSO, email-list auth, or a one-time PIN - so family members just click a link in an email and they are in. You now have a publicly routable hostname. Access policy is not optional; it is the only thing stopping the internet from pinging your light switches.
Nabu Casa Zero config. Pay-it-and-forget. TLS everywhere, auth included, voice assistants out of the box. The path of least resistance if you do not own a domain. Subscription fee. Total dependency on Nabu Casa's control plane. I have not personally used it.
Reverse proxy at home No third-party dependency. A home router forwards 443 to a static-IP Pi that proxies into the van via Tailscale. Three things have to stay up and agree: home router, home Pi, and the van. When it works it is free. When one piece moves it breaks.

My current setup is Tailscale for me, Cloudflare Tunnel for anyone else. Tailscale on my phone and laptop means I can SSH into the Pi, load the dashboard, and reach the Cerbo's web UI at its LAN IP from a cafe in Perpignan. Cloudflare Tunnel is what I hand to my partner so she can check battery state from her phone without installing anything, and what I would hand to a friend-of-the-family in an emergency. The Tunnel is locked behind Cloudflare Access with her email on the allowlist.

I have not paid for Nabu Casa. If I did not already own a domain I probably would.

Cerbo on the tailnet without running Tailscale on the Cerbo

Victron's Venus OS cannot run Tailscale (no supported binary for the Cerbo's hardware, and I would not install one in a running energy system anyway). So the Cerbo is reachable over Tailscale via the Pi. On the Pi I enabled tailscale up --advertise-routes=192.168.1.0/24. Any tailnet peer with --accept-routes enabled can now curl the Cerbo directly at its LAN IP. The Pi is acting as a subnet router for the van LAN.

# On the Pi, once, to expose the van LAN to the tailnet
tailscale up --advertise-routes=192.168.1.0/24

# On any device that wants to reach the Cerbo directly
tailscale up --accept-routes

Backups and resurrection

Home Assistant snapshots (Supervisor → Backups) nightly to the SSD. The Google Drive Backup add-on pushes the latest snapshot off-site weekly. If the Pi melts on a French aire the recovery is: new Pi, flash HAOS, restore latest snapshot from Google Drive on first boot. That is the recipe. It has been done twice.

Known gotchas in this stack

Whats next on this page

If there is a specific corner of this stack you want me to document sooner, email [email protected]. I add whatever people actually want to read next.