Hoe werkt dit huis?

Dit is geen dashboard vol tabellen, maar je eigen huis met de energie die er live doorheen stroomt. Hieronder leg ik elk onderdeel uit in gewone taal. Wil je de techniek erbij weten? De schuif rechtsboven staat standaard op Pro — dan staat overal “onder de motorkap” open, met de echte MQTT-onderwerpen, instellingen en commando’s erbij. Zet ’m op Beginner voor alleen het verhaal.

De homepage

De voorpagina is je huis in één oogopslag. Een foto van het echte huis als achtergrond, met zwevende “glas”-kaartjes erover die elk een stukje van je energie laten zien — en rustige lichtlijntjes die tonen wáár de stroom naartoe gaat.

Dit is de échte homepage, live in beeld — het verandert mee met de werkelijke waarden en het weer. Open de homepage →

Wat je ziet:

  • De foto van het huis past zich aan het actuele weer en tijdstip aan: ochtend, dag, schemering en nacht, met aparte versies bij regen en bewolking.
  • De zwevende widgets — zon (opwek), batterij (vol/leeg + laden of ontladen), net (afname of teruglevering), huisverbruik, de auto, gas en water.
  • De lichtlijntjes met bolletjes laten de richting zien: zon → huis, batterij → huis, of huis → net als je teruglevert.
  • Twee grafieken onderaan: het vermogen van de laatste 24 uur, en per dag wat je opwekte en verbruikte.

Op dit moment maken je panelen . live, net als op de echte pagina

Sensor MQTT Node-server Jouw scherm
  • Server-side first-paint: de server zet de laatste waarden meteen als tekst in de HTML, zodat de pagina direct in beeld staat — nog vóór er JavaScript draait.
  • Daarna live: bijna alles in huis praat MQTT — een licht berichten-protocol waarbij elk apparaat zijn waarde op een “onderwerp” (topic) publiceert. Een bridge op de server luistert mee en duwt updates naar je scherm (SSE). Er is bewust géén open data-API.
  • De achtergrondfoto wordt opgebouwd door sky-vision: een buitencamera gericht op de lucht levert een beeld, een lokaal AI-model (via Ollama) beoordeelt daaruit de actuele luchttoestand, en in combinatie met het Davis-weerstation kiest het systeem de best passende foto uit de set, met een zachte cross-fade.
  • De lichtlijntjes tekent een animatie-engine over een onzichtbare SVG, verankerd op vaste coördinaten in de foto, zodat ze precies op het dak, de mast en de auto landen.

De bronnen die hier samenkomen: een eigen P1-slimmemeter (ESPHome), GoodWe + Hoymiles (zon), Marstek-accu’s via RS485, de BMW (auto), Frank Energie (prijzen) en het Davis-weerstation. Hóe elk apparaat precies wordt uitgelezen — en waarom dat per merk anders gaat — lees je in de aparte secties hieronder.

Stack: Node.js + Express · MQTT · MySQL · vanilla HTML/CSS/JS (geen frameworks).

Zonnepanelen

Op het dak liggen twee verschillende zonne-installaties van twee merken. Samen zo’n 24 panelen, goed voor ongeveer 10 kWp — op een zonnige dag samen 30 à 36 kWh.

GoodWe

Eén grotere string-omvormer (model 3600-DNS) met de panelen in twee reeksen ("strings"): 5 panelen op de ene, 8 op de andere.

Hoymiles

Elk paneel heeft z’n eigen micro-omvormer. Drie van die micro’s, samen 11 panelen — daardoor is het vermogen per paneel zichtbaar.

Wat de panelen opwekken gaat eerst naar het huis, dan in de accu, en pas het overschot daarna terug het net op. En precies dat overschot kun je terugregelen als teruglevering even niets waard is — zie hieronder.

Uitlezen

  • GoodWe wordt uitgelezen via RS485 (Modbus over de seriële bus van de omvormer): AC-vermogen, beide strings, temperatuur en de teruglever-limiet. De omvormer meet wél het vermogen per string, maar geen energie per string — de dag-kWh per string wordt daarom berekend door het gelogde stringvermogen te integreren en te schalen naar de gemeten dagopbrengst.
  • Hoymiles gaat anders: een klein OpenDTU-kastje praat draadloos met de micro-omvormers en publiceert per paneel het vermogen en de dagopbrengst via MQTT.
  • Het verschil in één zin: GoodWe = één omvormer voor meerdere panelen (RS485), Hoymiles = één omvormer per paneel (OpenDTU).

Terugregelen bij negatieve prijzen

Soms is de stroomprijs negatief: je betáált dan om terug te leveren. Zodra de accu’s vol zijn én de prijs negatief is, knijpt het systeem de teruglevering dicht via een MQTT-commando — helemaal uit, of gedeeltelijk (bijv. 40%).

publishgoodwe_1/cmd/export_limit
0→ teruglevering helemaal uit
40→ 40% = ±1440 W (deels terugregelen)
100→ vol vrij = 3600 W
  • Hoymiles regelt per omvormer terug via OpenDTU: hoymiles/<serial>/cmd/limit_nonpersistent_relative (een percentage), of helemaal uit met .../cmd/power0.
  • Veiligheidsnet: blijft de GoodWe-limiet te lang onder 100% staan, dan zet een watchdog ’m automatisch terug op vol — zo blijft teruglevering nooit per ongeluk afgeknepen nadat de negatieve uren voorbij zijn.
  • De beslissing zélf (“accu vol én prijs negatief”) komt niet uit de omvormer maar uit een aparte regel-engine; zie Stroomprijzen en Batterij & EMS.

Batterij & EMS

Een thuisaccu (drie Marstek-units) slaat overdag de overtollige zonnestroom op, zodat je ’m ’s avonds kunt gebruiken in plaats van duur van het net te kopen. Een eigen EMS (energiemanagementsysteem) bepaalt elk moment wat de accu’s doen.

Het brein: twee strategieën

Meter op 0

Houd de meter op nul: lever precies genoeg uit de accu om netafname te voorkomen, en laad juist het overschot op. De standaard.

Prijs-gestuurd

Volg de uurprijs: laad als stroom goedkoop is, ontlaad als die duur is. Zo benut je het prijsverschil.

Wil je zien hóe goed dit draait? Het live EMS-dashboard toont elke beslissing, en het Dagreport geeft per dag een EMS-score met gemiste opslag, onnodige netstroom en schakel-activiteit.

Eigen RS485, eigen P1 — niet de Marstek-app

De Marstek-app en de meegeleverde Marstek-P1 bleken niet stabiel genoeg om de accu’s strak op te sturen. Daarom gaat hier alles via een eigen RS485/Modbus-koppeling én een eigen ESPHome-P1 slimmemeter — lokaal, zonder cloud, met elk commando direct teruggelezen ter controle.

Eigen P1 (ESPHome) MQTT EMS RS485/Modbus Marstek
  • De eigen SlimmeLezer (ESPHome) leest de P1-poort en publiceert het netvermogen per fase via MQTT (slimmelezer-eth/sensor/power_consumed_phase_1/state enz.). Per fase, want elke accu hangt aan één fase.
  • De EMS rekent elke 5 seconden en stuurt elke accu een commando:
publishmarstekrs485/marstek_1/cmd/in/set_mode
{ "mode": "charge", "power_w": 1500 }
  • Een RS485-driver vertaalt dat naar Modbus-registers in de Marstek (Venus): vermogen zetten, de controlemodus aanzetten, en de richting kiezen. Daarna leest hij de toestand terug; de EMS herbevestigt via het gemeten AC-vermogen en stuurt na 60 s opnieuw als het commando niet “pakte”.
42000
controlemodus aan/uit (0x55AA / 0x55BB)
42010
richting — 0 stop · 1 laden · 2 ontladen
42020 / 42021
laad- / ontlaadvermogen (W)
32104 / 32202
terug­gelezen: SOC (%) · AC-vermogen (W)

Instellingen om de accu’s perfect te laten draaien

In de EMS-instellingen zit een hele rij knoppen waarmee je het gedrag fijn afstelt:

Strategie
“Meter op 0” of “Prijs-gestuurd”.
Deadband & hysterese
stille zone rond 0 W + extra marge, zodat de accu niet “klappert” bij kleine schommelingen.
Tijdvertraging
een nieuwe modus moet eerst een paar seconden stabiel zijn voor hij echt schakelt.
Max laad / ontlaad
vermogensplafond per batterij (W).
Min / Max SOC
reserve-ondergrens (onder de min wordt niet ontladen) en bovengrens per batterij.
Fase & laad/ontlaad-vanaf
welke fase een accu bedient, en bij welk vermogen een volgende accu meedoet (verdeling).
Prijsdrempels
laden onder een ingestelde €/kWh, ontladen erboven.
Leegrijden vs. balanceren
eerst één accu leeg, of alle accu’s gelijk verdelen.
Feed-forward bronnen
zware pulslasten (inductie, was/droger, vaatwasser) vooraf opvangen, zodat je daarvoor geen net hoeft te gebruiken.
Meet-modus / dry-run
alles berekenen en tonen zónder echt te sturen — handig om af te stellen.

Bij een negatieve prijs in prijs-modus laadt de EMS bewust door (laagste SOC eerst): je slaat dan zo veel mogelijk op, en zodra alles vol is, gaat de teruglevering van de panelen dicht (zie Zonnepanelen). Op de showcase zie je dit read-only: het batterij-vermogen dat je ziet, ís het EMS-commando.

Net & verbruik

Het net is het vangnet: maak je minder dan je gebruikt, dan neem je het tekort van het net; maak je meer, dan lever je het overschot terug. De slimme meter meet beide kanten op.

Huisverbruik is alles wat het huis op dat moment samen gebruikt — de warmtepomp, apparaten, en de auto als die thuis laadt.

  • De slimme meter wordt uitgelezen door een eigen ESPHome-“SlimmeLezer” op de P1-poort. Die publiceert het vermogen per fase én de totalen via MQTT — dezelfde meter die ook de EMS voedt.
  • Dat per-fase meten is belangrijk: elke thuisaccu hangt aan één fase, dus de EMS moet per fase weten of er wordt afgenomen of teruggeleverd.
  • Het netto net = afname − teruglevering. Het dag-huisverbruik wordt opgebouwd uit zon-direct + uit-de-accu + netafname.
topicslimmelezer-eth/sensor/power_consumed_phase_1/state
230→ 230 W afname op fase 1

De auto

De elektrische auto (een BMW) verschijnt op de homepage. Laadt-ie thuis, dan zie je de energie van het huis naar de auto stromen; laadt-ie elders, dan staat dat los — zonder stroomlijn vanuit huis.

De auto geeft ook z’n locatie (GPS) door, maar die wordt nooit naar deze publieke pagina gestuurd — privacy gaat voor.

  • De auto publiceert via MQTT z’n laadstatus, accupercentage en actieradius.
  • “Thuis laden” wordt afgeleid uit de thuis-laadpaal: meet die meer dan een drempelvermogen, dan laadt de auto thuis en voedt de huis→auto-flow.
  • De GPS-coördinaten uit de auto-bridge worden server-side bewust weggelaten.

Weer & foto

De achtergrondfoto van het huis verandert mee met het échte weer en het tijdstip: ochtend, dag, schemering, nacht, en aparte versies bij regen en bewolking.

Buitencamera Davis-weerstation AI Passende foto
  • Het Davis-weerstation levert live temperatuur, luchtvochtigheid, UV en regen.
  • sky-vision: een buitencamera gericht op de lucht levert een beeld, een lokaal AI-model (via Ollama) beoordeelt daaruit de luchttoestand, en samen met het weerstation kiest het systeem de best passende foto — met een zachte cross-fade.

Stroomprijzen

Met een dynamisch contract (Frank Energie) heeft stroom elk uur een andere prijs: vaak goedkoop ’s nachts en rond de zonnige middag, duur in de avondpiek.

De prijs die telt is de “all-in”-prijs: marktprijs + belastingen + opslag — dat is wat je daadwerkelijk per kWh betaalt.

  • De uurprijzen komen via MQTT binnen — zowel de kale marktprijs als de all-in prijs, plus een aparte “negatief”-vlag voor uren waarin je geld toe krijgt.
  • De EMS gebruikt die prijs om de accu te timen: laden onder een drempel, ontladen erboven.
  • De negatief-vlag is de trigger achter het terugregelen van de panelen: is de prijs negatief én zijn de accu’s vol, dan knijpt een regel-engine de teruglevering dicht (zie Zonnepanelen).
topicenergieprijzen/frank/stroom/huidig/negatief
{ "negatief": true }

Op de zon-pagina kleurt de prijs-strip groen (goedkoop), grijs (normaal), oranje (duur) of paars (negatief) — dezelfde drempels die de EMS gebruikt.

Techniek & veiligheid

De hele site is read-only: je kunt alles live volgen, maar er kan vanaf hier niets worden gewijzigd. Gebouwd om snel én veilig te zijn.

MQTT Node + Express MySQL Jouw scherm
  • Stack: Node.js + Express, een MQTT-bridge, MySQL (alleen lezen), en gewone HTML/CSS/JS zonder frameworks. Grafieken via een lokaal meegeleverde Chart.js.
  • Live: de server zet de laatste waarden meteen in de HTML (first-paint) en duwt daarna updates via MQTT → SSE. Er is geen open data-API.
  • Automatisering: een aparte regel-engine luistert naar álle MQTT-onderwerpen als “feiten” en kan acties terugsturen — zo ontstaat o.a. het terugregelen van de panelen bij negatieve prijzen.
  • Veilig: strikte CSP (geen losse scripts of inline-stijl), alleen GET, een ondertekend token-cookie + snelheidslimiet + auto-ban tegen scrapers, en alles strikt same-origin.

Privacy

Deze site is een persoonlijke showcase, geen commerciële dienst. Hieronder kort en eerlijk wat er gebeurt als je ’m bezoekt.

Wat wordt vastgelegd

  • Een bezoek-registratie: je IP-adres (voor regio/land via geo-lookup), browsertype, tijd-op-pagina, welke secties je bekeek en de gekozen taal.
  • Dit dient uitsluitend voor anonieme bezoekersstatistiek en beveiliging (het weren van scrapers).

Géén accounts, géén advertenties en geen trackers van derden. Alles blijft op deze server; niets wordt gedeeld of doorverkocht.

Cookies

Er wordt één functionele cookie gebruikt: een beveiligingstoken tegen geautomatiseerd uitlezen. Die is strikt noodzakelijk voor de werking, dus daarvoor is geen toestemmingsvenster nodig.

Jouw rechten

Wil je weten wat er over jouw bezoek is vastgelegd, of dat laten verwijderen? Neem dan contact op met de eigenaar van bwired.nl.

Laatst bijgewerkt: juni 2026 · concept, nog te controleren.