Skip to Content
Smart terrarium

Home Assistant Integration

My terrarium tracks the live weather of the Solomon Islands, the skinks' own range, then learns how to hold that climate on its own, and logs every reading.

Instead of picking fixed numbers, I let the terrarium follow the skinks' native climate in real time. Home Assistant pulls the current Solomon Islands sunrise, sunset and humidity and uses them as live targets: the lights rise and set with the island sun, and a self-learning controller keeps humidity tracking the island's own value. Everything is logged, which is as useful for the behaviour notes and the paper I'm writing as it is for day-to-day welfare.

This page is the whole thing, start to finish: the idea, the diagrams that explain each part, a browsable record of every day the system has run, and the full parts list if you want to build the same. Nothing below is illustrative. Every number comes out of the enclosure.

📦 Open-source config The whole build, controller, sensors, lighting and dashboard, will live in a public GitHub repository so other keepers can reuse it.

Island sync, the core idea

A weather source for the Solomon Islands feeds three live reference values into Home Assistant: sunrise, sunset and humidity. The photoperiod and the humidity target then follow the real island rather than a static schedule, so the animals experience something close to their wild day, drifting naturally across the seasons.

Diagram: live sunrise, sunset and humidity from the Solomon Islands feeding the terrarium's lighting and humidity targets.
The island supplies the shape of the day. My enclosure has to translate that shape into something a heated glass box can actually hold.

Lighting: following the island sun

  • Basking light follows the Solomon sunrise/sunset cycle for its timing (when it's on), but its temperature is held by a separate Habistat dimming thermostat, not by Home Assistant (see below).
  • ESP32 LED bar (ESPHome, "lumenize") provides the bright daylight the species needs and ramps with the same cycle, sunrise, full day, sunset.
  • The result is a consistent, natural photoperiod without me touching a timer.

Three zones, not one number

Temperature and humidity are measured in three zones, top, ambient and center, so the controller sees the gradient, not one number. From each it also computes dew point and VPD (vapour-pressure deficit), the same figures a good hygrometer app shows, which are a better guide to how "drying" the air really feels to the animal than raw humidity alone.

This matters more than I expected when I built it. A tall enclosure heated from the top is stably stratified: warm air sitting above cool air does not convect, so the layers genuinely do not mix on their own. On a still afternoon the canopy of my enclosure can hold ten degrees more dew point than the middle, which means the box is simultaneously too wet at the top and too dry where the animals actually sit. One sensor in the middle would have told me everything was fine.

Diagram: the three measured zones of the enclosure, top, ambient and center.
Three sensors, three microclimates. The controller decides on the spread, not on an average that hides it.

The controller: a self-learning climate brain

The humidity and ventilation are run by a custom controller (an AppDaemon app) rather than simple on/off rules. Reacting to the current reading is the easy half. The rest is learning my specific enclosure and working out where it is heading. Every few minutes the controller:

  • Learns how much each second of misting raises humidity, and how much each second of fan lowers it, separately per zone and per temperature, and remembers it across restarts.
  • Predicts when humidity will fall below target from the measured drying rate, and mists early instead of waiting.
  • Ventilates against fungus, if two of three zones sit too high, it runs a measured fan burst.
  • Helps with heat, heating itself is held by the Habistat thermostat (below), but on a hot spell the controller adds evaporative cooling by misting or venting.
  • Guards against over-misting, caps a spray if a zone is already near saturation.
  • Fails safe: if all sensors drop out it enters a "safe mode" and mists on a learned schedule so the animals are never left dry; a "refill mode" pauses everything while I top up the water tank.

What happens every five minutes

The controller wakes on a five-minute tick and works down a fixed priority list, stopping at the first rule that applies. Nothing runs in parallel, so no two rules can ever be pulling against each other. Months later, when I am trying to work out why a particular afternoon went the way it did, there is only one rule to find.

Diagram: the controller's five-minute decision cycle, from reading the sensors down through the priority list to an action.
One pass, top to bottom, every five minutes. Safety rules sit above comfort rules, so the enclosure can never be misted into a problem it is already in.

Why the humidity target has a ceiling

Chasing the island's humidity number directly would be a mistake, for two reasons. The first is that the islands have wind and my living room does not. Air moves constantly through a forest canopy, so 90% out there is 90% of air that is being replaced all day and never sits against a surface. In a closed glass box the same air just stands there, and stagnant wet air is a different thing entirely from moving wet air.

The second is condensation. Warm air holds far more water than cool air. If I fill a 35 °C enclosure to the island's 90% and then let the night fall to 22 °C, all of that extra water has to go somewhere, and it goes onto the glass, the cork and the leaves. Wet surfaces overnight are how you grow mould and how a healthy enclosure turns into a sick one.

So the controller computes the dew point of each zone and caps the humidity target below the coldest temperature the enclosure has actually reached in the last 24 hours. Not an assumed night temperature, a measured one. The target is allowed to follow the island right up until following it would guarantee water on the glass by morning.

Diagram: how the dew-point ceiling limits the humidity target so the enclosure does not condense overnight.
The ceiling is the whole reason this is not a thermostat with a humidity dial. What is safe at noon is not safe at four in the morning.

How it learns

Every actuator run is an experiment. The controller records the humidity before a misting, waits for the air to settle, and records it again, then folds the difference into a running estimate of how much this enclosure responds to one second of water. The same happens for the fan, and for the rate at which the box dries out on its own. All of it is kept per zone and per temperature band, because a spray on a 36 °C afternoon behaves nothing like the same spray at 25 °C.

The practical effect is that the enclosure gets better at being itself. I did not measure any of these numbers by hand and I could not have: they change with the season, the planting and how much water is in the substrate.

Diagram: the learning loop, act, wait, measure the response, update the stored estimate.
Act, wait, measure, update. The stored estimates survive restarts, so the enclosure does not forget what it learned last month.

Browse every day

Every day the system has run, drawn entirely from the log, nothing smoothed and nothing drawn by hand. Each one shows the island line, the target the controller derived from it, the humidity it actually achieved, the temperature underneath driving all of it, and every misting and fan run along the bottom.

Step through with the arrow keys or the strip, switch on the three zones to see the stratification, put the Groningen outdoor temperature underneath to see what the box was working against, and use compare to put any two days on top of each other. Pick a hot one and you can watch the heat ladder work: fan first, then a cooling misting, then cutting the basking lamp if neither is enough.

Humidity, target, trigger, temperature and every misting come from the controller's own append-only log. Fan runs come from Home Assistant's recorder, which keeps about ten days, so older days show no fan trace. The Solomon Islands lines are reconstructed from the Open-Meteo archive using the same lookup the live sensor performs, which reproduces the recorded sensor values with a median error of 0.00% over the period where both exist. The Groningen line is the same archive read for this city on the local clock, so it lines up hour for hour with the mistings underneath it.

Making a rainy season

If you step through the days above you will notice something change on 20 August: the green target stops tracking the islands and sits flat on 70% for about twelve hours a day. Nothing went wrong there, I raised the humidity floor by hand.

Emerald tree skinks come into breeding condition on the wet season, when humidity stays high and food is suddenly everywhere. So I am running both levers at once: I raised the humidity floor to hold the enclosure wet through the day, and I increased how much and how often the animals are fed. Together those two signals are the closest I can get to telling them the rains have arrived, which is what I want if they are going to pair up.

The cost is visible in the same chart. Holding a floor that high overrides the dew-point ceiling on warm afternoons, which is exactly the protection I described above, so more water ends up on the glass overnight. That is a trade I am making deliberately and watching closely, not one the system made for me. Before the 20th the floor was 60%, and before the 17th it was 50%, which is why the earlier days in the browser look so different.

Temperature is hardware-controlled

Software never holds the heat The basking lamp is wired through a Habistat dimming thermostat, which holds the hot spot on its own. Home Assistant reads temperature in all three zones but cannot add heat. Cooling is the one direction it can push, and it does that by misting, so on a hot afternoon the spray I use for humidity is also the spray doing the cooling.

I would recommend this split to anyone. A crashed server, a failed update or a bug in my own code cannot cook the enclosure, because the thing that decides how hot the basking spot gets is a dumb analogue thermostat with no opinion about any of it. Everything Home Assistant does is a refinement on top of a safe baseline.

Behaviour log

A quick form in Home Assistant lets me log what each skink, Loki, Naga and Ron, is doing: activity, appetite, shedding status and a note. Each entry saves a full snapshot of the moment: temperature, humidity, dew point and VPD for all three zones, plus the outdoor weather. Weeks later I can scan for patterns, a dip in activity or appetite lined up against a change in the terrarium, which is exactly the kind of data that feeds the scientific side of this project.

The camera doing the watching is a Wyze Pan v4, and mounting it took no bracket at all: the foot is magnetic, so the camera hangs inside the enclosure off a magnet laid on top of the mesh lid. Nothing drilled, nothing glued, and I can lift it out one-handed when I need to.

View from the terrarium camera inside the enclosure
The in-terrarium camera earns its keep, half the behaviour notes come from catching them on this when I'm not in the room. © Floris Anthony Feiner

Monitoring & alerts

  • Sensor watchdog, I get a phone alert the moment a sensor goes offline, and again when it recovers.
  • Safe-mode & action alerts: entering safe mode, and each spray or fan run, are pushed to my phone.
  • Live dashboard: learned drying rate, time-to-threshold, spray gain and the current targets are all shown so I can see the brain's reasoning at a glance.

Every decision: spray, fan, learned value, sensor drop-out, is written to a permanent append-only log, so I have a full record of what the terrarium did and why. That log is what the day browser above reads.

What I would change

Two things, and I would rather write them down than pretend the build is finished.

The fan is the wrong tool for mixing. Mine exhausts to the room, so every time it breaks up the stratified canopy it also dries the whole enclosure. A small internal circulation fan, moving air inside the box without exchanging it with the room, is the physically correct answer to a thermal inversion, and would let the exhaust fan go back to being used only for genuine humidity removal.

The humidity floor and the dew-point ceiling have no idea about each other. Right now I am holding a high floor on purpose, for the reasons in the rainy-season section, and the consequence is that the ceiling is overridden for half of every warm day. I am fine with that because I chose it. What I would change is that the controller has no way of knowing the difference between a floor I raised deliberately and a floor that is silently cancelling a safety rule. A seasonal mode that said "wet season, accept the condensation risk, and tell me about it" would be more honest than two rules quietly fighting.

What it takes to build

Here's what it takes to build the same thing.

Hardware

PartRoleCount
Home Assistant server (HA Green/Yellow, Pi 4/5, or mini-PC)Runs everything1
Temp/humidity sensors (e.g. Inkbird IBS-TH)One per zone, top, ambient, center3
Bluetooth adapter/proxy + a Matter hubConnects the sensors & the plugs to HA1
Tuya Wi-Fi mister (AliExpress)Humidity, self-contained reservoir + nozzle, controlled over Tuya1
IKEA Matter smart plug(s), e.g. the fanControlled airflow & other switched devices1+
Basking heat lamp + Habistat dimming thermostatDaytime hot spot, temperature held in hardware, not HA1
ESP32 + addressable LED bar (ESPHome)Daylight / photoperiod1
Camera (I use a Wyze Pan v4)Behaviour watching, magnetic foot on a magnet on the mesh lid, no bracket1
Phone running the HA appAlerts & dashboard1

Home Assistant software & plugins

ComponentWhat it's for
Home Assistant OS / CoreThe platform itself
AppDaemon add-onRuns the self-learning terrarium controller (Python)
ESPHome add-onFirmware for the ESP32 LED bar
Tuya / LocalTuya integrationControls the Wi-Fi mister
Matter integrationIKEA smart plugs (fan & other switched devices)
Bluetooth / Inkbird integrationReads the BLE temp/humidity sensors
A weather source for the Solomon Islands (I use Open-Meteo)Live sunrise, sunset & humidity reference
Template sensorsCompute dew point & VPD from temp + humidity
Helpers (input_boolean / input_number / input_select / input_text)Refill mode, live spray/fan duration, behaviour-log fields
Scripts & LogbookBehaviour logging with condition snapshots
HACS + custom Lovelace cardsThe dashboard
HA Companion appPush notifications
Built on my hardware The plugs, lamps and sensors here tie back to the kit on my terrarium & equipment page: that parts list and this integration are documented together.

Another keeper-built tool worth knowing

Automating a terrarium is one way to take the guesswork out of it. Simulating one before you build it is another. Light My Reptile, built by Nathan Burton, models UVB, heat and visible light inside a specific enclosure and draws UV Index contours across a cross-section, so you can see where the basking branch should sit before you spend anything. The emerald tree skink is not in its species list, so the settings to enter for this species are written up on the terrarium page.