Mijn huis is mijn lab. Elke kamer heeft sensoren. Elk apparaat communiceert via een centrale broker. En ondertussen draaien er AI agents die patronen herkennen, anomalieën signaleren en automatisch actie ondernemen. Klinkt futuristisch? Dat is het niet — met ESP32, MQTT, Home Assistant en een klein beetje Python is dit vandaag volledig haalbaar voor ieder. In dit artikel laat ik je zien hoe ik het stap voor stap heb opgebouwd, inclusief alle code en configuratie.
De architectuur in één oogopslag
Voordat we in de code duiken, is het belangrijk om het grote plaatje te begrijpen. Het systeem bestaat uit drie lagen. De eerste laag zijn de ESP32-nodes: kleine microcontrollers met sensoren die overal in huis hangen. Ze meten temperatuur, luchtvochtigheid, beweging, licht en luchtkwaliteit. De tweede laag is de MQTT-bus: een lichtgewicht publish/subscribe protocol waarover alle nodes communiceren met een centrale Mosquitto broker op een Raspberry Pi. De derde laag is de intelligence laag: Home Assistant verwerkt de data en toont dashboards, terwijl Python AI agents op de achtergrond patronen analyseren en slimme automatiseringen triggeren.
- ESP32 DevKit C — microcontroller per ruimte
- DHT22 — temperatuur & luchtvochtigheid
- PIR HC-SR501 — bewegingsdetectie
- BMP280 — luchtdruk & hoogte
- MQ-135 — luchtkwaliteit (CO₂ indicatie)
- Mosquitto MQTT broker op Raspberry Pi 4
- Home Assistant OS op dezelfde Pi
- Python AI fleet op mijn lokale server
Stap 1: ESP32 nodes opzetten
Elke ESP32 node heeft dezelfde basis firmware. Ik gebruik Arduino-framework met PlatformIO voor dependency management. De node verbindt met WiFi, leest alle aangesloten sensoren uit, en publiceert de data elke 30 seconden op een gestructureerd MQTT topic. Het topic-schema is cruciaal — ik gebruik een hiërarchie die Home Assistant automatisch kan ontdekken via MQTT Discovery.
// platformio.ini
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
lib_deps =
knolleary/PubSubClient@^2.8
adafruit/DHT sensor library@^1.4.4
adafruit/Adafruit BMP280 Library@^2.6.8
// main.cpp — vereenvoudigd
#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>
#include <ArduinoJson.h>
const char* ROOM = "woonkamer"; // Per node aanpassen
const char* MQTT_HOST = "192.168.1.10";
DHT dht(4, DHT22);
WiFiClient espClient;
PubSubClient mqtt(espClient);
void publishSensorData() {
StaticJsonDocument<256> doc;
doc["temp"] = dht.readTemperature();
doc["humidity"] = dht.readHumidity();
doc["room"] = ROOM;
doc["uptime"] = millis() / 1000;
char payload[256];
serializeJson(doc, payload);
// Topic: huis/{room}/klimaat
String topic = String("huis/") + ROOM + "/klimaat";
mqtt.publish(topic.c_str(), payload, true); // retained = true
}
void loop() {
mqtt.loop();
static unsigned long last = 0;
if (millis() - last > 30000) {
publishSensorData();
last = millis();
}
}Stap 2: MQTT Discovery voor Home Assistant
Home Assistant heeft een krachtige MQTT Discovery feature: als een device een configuratiebericht publiceert op een speciaal topic, registreert HA het apparaat automatisch zonder dat je YAML hoeft te schrijven. Dit maakt het toevoegen van nieuwe ESP32 nodes triviaal — één publicatie en de sensor staat in je dashboard.
void registerWithHomeAssistant() {
// Publiceer discovery configuratie voor temperatuursensor
String config_topic = "homeassistant/sensor/esp32_"
+ String(ROOM) + "_temp/config";
StaticJsonDocument<512> cfg;
cfg["name"] = String(ROOM) + " Temperatuur";
cfg["unique_id"] = String("esp32_") + ROOM + "_temp";
cfg["state_topic"] = String("huis/") + ROOM + "/klimaat";
cfg["value_template"] = "{{ value_json.temp }}";
cfg["unit_of_measurement"] = "°C";
cfg["device_class"] = "temperature";
// Device info — groepeert sensoren per kamer
JsonObject device = cfg.createNestedObject("device");
device["identifiers"][0] = String("esp32_") + ROOM;
device["name"] = String("Sensor ") + ROOM;
device["model"] = "ESP32 DHT22";
device["manufacturer"] = "VorstersNV DIY";
char payload[512];
serializeJson(cfg, payload);
mqtt.publish(config_topic.c_str(), payload, true);
}Stap 3: Home Assistant — de optimale dashboard setup
Home Assistant dashboards kunnen er standaard nogal generiek uitzien. Met de juiste combinatie van custom cards en een doordachte layout maak je er een professioneel command center van. Ik gebruik drie dashboards: een overzichtsdashboard voor dagelijks gebruik, een analytics dashboard voor trends en patronen, en een systeem dashboard voor de gezondheid van alle nodes.
- HACS (Home Assistant Community Store) — voor custom cards
- mushroom-cards — moderne, compacte kaartjes per kamer
- mini-graph-card — mooie grafieken voor sensortrends
- apexcharts-card — geavanceerde visualisaties met meerdere series
- layout-card — flexibele grid layout voor het dashboard
- browser_mod — browser-specifieke instellingen en popups
# dashboard/woonkamer.yaml — Mushroom room card voorbeeld
type: custom:mushroom-template-card
primary: Woonkamer
secondary: >
{{ states('sensor.woonkamer_temperatuur') }}°C ·
{{ states('sensor.woonkamer_luchtvochtigheid') }}%
icon: mdi:sofa
icon_color: >
{% set temp = states('sensor.woonkamer_temperatuur') | float %}
{% if temp > 23 %} red
{% elif temp < 18 %} blue
{% else %} green {% endif %}
tap_action:
action: navigate
navigation_path: /lovelace/woonkamer-detail
# Mini-graph voor trends
- type: custom:mini-graph-card
entities:
- entity: sensor.woonkamer_temperatuur
name: Temperatuur
color: '#ef4444'
- entity: sensor.woonkamer_luchtvochtigheid
name: Vochtigheid
color: '#3b82f6'
hours_to_show: 24
points_per_hour: 4
line_width: 2
show:
labels: true
points: false
legend: trueStap 4: Automations — het huis laten reageren
Dashboards zijn leuk, maar automations zijn de echte kracht. Home Assistant automations worden beschreven in YAML en kunnen reageren op elke sensor, tijdstip of externe trigger. Mijn favoriete automations zijn de comfort-alerts (melding als een kamer te warm of te koud wordt), aanwezigheidsdetectie (koppeling met telefoon GPS), en energie-optimalisatie (apparaten uitschakelen als niemand thuis is).
# automations.yaml — Temperatuuralert
- id: temp_alert_slaapkamer
alias: "Alert: slaapkamer te warm"
trigger:
- platform: numeric_state
entity_id: sensor.slaapkamer_temperatuur
above: 24
for:
minutes: 10
condition:
- condition: time
after: "22:00:00"
before: "08:00:00"
action:
- service: notify.mobile_app_koen_telefoon
data:
title: "🌡️ Slaapkamer te warm"
message: >
Slaapkamer is {{ states('sensor.slaapkamer_temperatuur') }}°C.
Raam openzetten aanbevolen.
- service: mqtt.publish
data:
topic: "huis/ai/events"
payload: >
{"event": "temp_alert", "room": "slaapkamer",
"value": "{{ states('sensor.slaapkamer_temperatuur') }}",
"severity": "warning"}Stap 5: De AI fleet integreren
Tot hier is alles vrij standaard Home Assistant gebruik. Nu wordt het interessant. Ik heb een Python AI fleet draaien die luistert op het MQTT topic "huis/ai/events" en intelligent reageert. Elke sensor-anomalie triggert een event, de AI fleet analyseert het patroon over tijd, en kan aanbevelingen doen of zelfs automatisch ingrijpen. Het is de laag boven Home Assistant — niet ter vervanging, maar als intelligente co-piloot.
# ai_fleet/smart_home_agent.py
import json
import paho.mqtt.client as mqtt
from dataclasses import dataclass
from collections import deque
from datetime import datetime
@dataclass
class SensorEvent:
room: str
event_type: str
value: float
timestamp: datetime
class SmartHomeAgent:
"""AI agent die patronen detecteert in sensordata."""
def __init__(self, mqtt_host: str = "192.168.1.10"):
self.history: dict[str, deque] = {} # room -> laatste 100 events
self.client = mqtt.Client()
self.client.on_message = self._on_message
self.client.connect(mqtt_host)
self.client.subscribe("huis/#")
def _on_message(self, client, userdata, msg):
topic = msg.topic
try:
data = json.loads(msg.payload)
except json.JSONDecodeError:
return
room = topic.split("/")[1] if "/" in topic else "unknown"
if room not in self.history:
self.history[room] = deque(maxlen=100)
# Sla op in history
if "temp" in data:
event = SensorEvent(
room=room,
event_type="temperature",
value=data["temp"],
timestamp=datetime.now()
)
self.history[room].append(event)
self._analyze(event)
def _analyze(self, event: SensorEvent):
"""Analyseer of dit event afwijkt van het patroon."""
history = self.history.get(event.room, [])
temps = [e.value for e in history if e.event_type == "temperature"]
if len(temps) < 10:
return # Onvoldoende data
avg = sum(temps) / len(temps)
deviation = abs(event.value - avg)
if deviation > 3.0: # Meer dan 3°C afwijking
self._publish_insight(
room=event.room,
message=f"Ongewone temperatuurschommeling: {event.value:.1f}°C "
f"(gemiddelde: {avg:.1f}°C, afwijking: {deviation:.1f}°C)",
severity="warning" if deviation > 5 else "info"
)
def _publish_insight(self, room: str, message: str, severity: str):
"""Publiceer AI inzicht terug naar MQTT voor HA notificatie."""
payload = json.dumps({
"source": "ai_fleet",
"room": room,
"message": message,
"severity": severity,
"timestamp": datetime.now().isoformat()
})
self.client.publish("huis/ai/insights", payload)
print(f"[AI] {room}: {message}")
def run(self):
print("Smart Home AI Agent gestart...")
self.client.loop_forever()
if __name__ == "__main__":
SmartHomeAgent().run()Home Assistant luistert naar AI inzichten
De AI agent publiceert zijn inzichten op het topic "huis/ai/insights". Home Assistant heeft een automation die op dit topic luistert en de insights doorstuurde als notificatie of als kaartje op het dashboard. Zo heb je een bidirectionele koppeling: HA stuurt events naar AI, AI stuurt inzichten terug naar HA.
# configuration.yaml — MQTT sensor voor AI insights
mqtt:
sensor:
- name: "AI Inzicht Laatste"
state_topic: "huis/ai/insights"
value_template: "{{ value_json.message }}"
json_attributes_topic: "huis/ai/insights"
json_attributes_template: >
{{ {"room": value_json.room,
"severity": value_json.severity,
"timestamp": value_json.timestamp} | tojson }}
# automation — stuur AI inzicht als notificatie
- id: ai_insight_notification
alias: "AI Fleet: stuur inzicht als notificatie"
trigger:
- platform: mqtt
topic: "huis/ai/insights"
condition:
- condition: template
value_template: >
{{ trigger.payload_json.severity in ['warning', 'critical'] }}
action:
- service: notify.mobile_app_koen_telefoon
data:
title: "🤖 AI Inzicht — {{ trigger.payload_json.room }}"
message: "{{ trigger.payload_json.message }}"Energie dashboard: inzicht in verbruik
Naast klimaatbeheer heb ik ook slimme stekkers (Shelly Plus 1PM) gekoppeld via MQTT. Die meten het stroomverbruik van individuele apparaten. In combinatie met het HA Energy dashboard krijg ik per dag, week en maand een overzicht van wat de grote verbruikers zijn. De AI agent analyseert patronen: als een apparaat plots meer verbruikt dan normaal, kan dat wijzen op een defect — een vroege waarschuwing die me al eens een dure reparatie heeft bespaard.
Mijn smart home is geen gadget. Het is een lerende infrastructuur die me elke week iets nieuws vertelt over hoe ik woon, energie gebruik en kan optimaliseren.
Tips voor de optimale Home Assistant setup
- Gebruik een Raspberry Pi 4 met SSD (geen SD-kaart) — veel betrouwbaarder en sneller
- Zet Home Assistant OS op, niet de Docker versie — updates zijn eenvoudiger
- Gebruik MQTT retained messages voor sensoren — dan zijn waarden direct zichtbaar na herstart
- Maak aparte dashboards per doel: overzicht, analytics, systeem — één dashboard wordt snel onoverzichtelijk
- Gebruik Lovelace YAML mode voor versiecontrole van je dashboard config
- Backup automatisch via de ingebouwde Google Drive integratie
- Gebruik Node-RED voor complexe automations — visueel programmeren is veel makkelijker dan YAML
- Koppel je AI agent via MQTT, niet via de REST API — veel lichter en real-time
OTA updates: nooit meer fysiek bij de sensor
Een van de grootste ergernissen bij hardware projecten: je moet elke sensor fysiek bereiken om firmware te updaten. Met OTA (Over The Air) updates via het ArduinoOTA library stuur ik firmware updates via WiFi. Ik heb een eenvoudig Python script dat alle ESP32-nodes in het netwerk detecteert en de nieuwe firmware pusht. De nodes hervatten automatisch na de update en zijn binnen 30 seconden weer online.
# ota_updater.py — update alle ESP32 nodes via netwerk
import subprocess
import json
from pathlib import Path
NODES = {
"woonkamer": "192.168.1.101",
"slaapkamer": "192.168.1.102",
"keuken": "192.168.1.103",
"bureau": "192.168.1.104",
}
FIRMWARE = Path("build/esp32dev/firmware.bin")
def update_node(naam: str, ip: str) -> bool:
print(f"Updaten: {naam} ({ip})...")
result = subprocess.run([
"python", "-m", "esptool",
"--chip", "esp32",
"--port", f"socket://{ip}:3232", # OTA port
"--baud", "115200",
"write_flash", "0x10000", str(FIRMWARE)
], capture_output=True, text=True)
success = result.returncode == 0
status = "✅ OK" if success else f"❌ FOUT: {result.stderr[:100]}"
print(f" {naam}: {status}")
return success
if __name__ == "__main__":
results = {naam: update_node(naam, ip) for naam, ip in NODES.items()}
ok = sum(results.values())
print(f"\nResultaat: {ok}/{len(NODES)} nodes succesvol bijgewerkt")Wat ik geleerd heb
- Begin klein — één kamer, één sensor. Uitbreiden is eenvoudig als de basis goed zit.
- MQTT retained messages zijn essentieel — zonder retained heeft HA geen waarde bij herstart.
- Geef elke node een uniek, beschrijvend topic-schema — dit bespaart verwarring later.
- Home Assistant MQTT Discovery is magie — gebruik het, schrijf geen manuele YAML sensors.
- AI agents via MQTT koppelen is eleganter dan REST polling — real-time en lichtgewicht.
- Dashboard ontwerp is werk — mushroom-cards + layout-card is de beste combinatie.
- Sla sensorhistorie op in InfluxDB + Grafana voor langetermijnanalyse die HA self niet biedt.
- OTA updates zijn geen luxe maar een must — maak het vanaf dag 1 in je firmware.
Wil je zelf aan de slag? De volledige broncode van mijn ESP32 firmware, de Python AI agent en de Home Assistant YAML configuraties staan op mijn GitHub. Vragen of ideeën? Stuur me een bericht — ik help graag. En als je zelf een interessant smart home project hebt, hoor ik het ook graag!

