No description
  • HTML 45.5%
  • JavaScript 39.5%
  • C++ 10%
  • CSS 2.2%
  • Python 1.4%
  • Other 1.4%
Find a file
Markus Oswald 74e01b7620 Lager: Verdünnungsbeispiel nennt die Sorte, die im Kanister ist
Stand „KH-Nacht (Soda)", obwohl NaOH drin war — der Text nahm die feste
Lösung der Pumpe. Jetzt die Sorte der letzten Kanister-Buchung; ist sie
unbekannt oder kommt der Kanister nicht aus dem Lager, nur der Pumpenname.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 11:15:35 +01:00
.forgejo/workflows KH-Titration: Host-Test an simulierter Küvette; Verriegelung im NVS, Sondenwächter, Freigabe im Web 2026-09-17 23:34:23 +02:00
aquarien Prüfung bei jedem Push: geänderte Datei braucht eine neue Adresse 2026-11-05 09:44:37 +01:00
assets Y-Achsen: kein Bereich unter 0, wenn kein Wert darunter liegt 2026-11-07 08:41:03 +01:00
cr-rechner C&R: Haken speichert die Salinität danach, ohne Rückfrage 2026-11-06 10:12:07 +01:00
entwuerfe Seiteneffekt: Plankton nachts, Lichtnetz tagsüber, einstellbar im Konto-Menü 2026-10-26 19:57:31 +01:00
esp-firmware C und Lanthan: ein Schlüssel gilt, Einstellungen springen nicht mehr (Firmware 0.21.1) 2026-11-06 13:10:26 +01:00
geraete Prüfung bei jedem Push: geänderte Datei braucht eine neue Adresse 2026-11-05 09:44:37 +01:00
icp Y-Achsen: kein Bereich unter 0, wenn kein Wert darunter liegt 2026-11-07 08:41:03 +01:00
kalk Y-Achsen: kein Bereich unter 0, wenn kein Wert darunter liegt 2026-11-07 08:41:03 +01:00
khtester Y-Achsen: kein Bereich unter 0, wenn kein Wert darunter liegt 2026-11-07 08:41:03 +01:00
lager Lager: Verdünnungsbeispiel nennt die Sorte, die im Kanister ist 2026-11-07 11:15:35 +01:00
nutrient Y-Achsen: kein Bereich unter 0, wenn kein Wert darunter liegt 2026-11-07 08:41:03 +01:00
pb_hooks Wirkfaktor und Verdünnung: vom Lager bis zur Dosis 2026-11-05 08:49:59 +01:00
pb_migrations Alte Wirkfaktoren aus den Nährstoff-Einstellungen räumen, Pläne neu rechnen 2026-11-05 08:51:16 +01:00
salz C&R: Haken speichert die Salinität danach, ohne Rückfrage 2026-11-06 10:12:07 +01:00
server Forgejo: Mailversand mit dem SMTP-Zugang von PocketBase 2026-10-10 00:50:13 +02:00
spurenrechner Prüfung bei jedem Push: geänderte Datei braucht eine neue Adresse 2026-11-05 09:44:37 +01:00
tools Dosenzeiten im Plan Stunde für Stunde wie der ESP: Rampen überstehen die Zeitumstellung 2026-11-06 13:10:26 +01:00
.gitignore Werkzeuge: lokale PocketBase, Firmware-Build wie die CI, Server-Deploy ohne Rückfrage 2026-10-09 18:46:02 +02:00
datenschutz.html Lager & Rezepte: Vorrat mit Reichweite und Nachbestell-Erinnerung, Abzug aus allen Rechnern 2026-09-24 10:30:10 +02:00
deploy.list Mehrere Aquarien, Schritt D (2): Startseite, Meine Aquarien, Meine Geräte 2026-10-10 16:26:56 +02:00
FIRMWARE.md pH-Obergrenze: Max des pH-Fensters sperrt die Nacht-Lösung (Firmware 0.20.0) 2026-10-26 18:59:40 +01:00
impressum.html Domain-Umzug: fishtankpro.de → reeftank.pro, Firmware 0.16.1 2026-09-23 19:45:44 +02:00
index.html Dosenzeiten im Plan Stunde für Stunde wie der ESP: Rampen überstehen die Zeitumstellung 2026-11-06 13:10:26 +01:00
KH-TESTER-INTEGRATION.md KH-Tester: Nachfüllen während einer Messung geht nicht mehr verloren (Firmware 0.20.1) 2026-10-29 08:57:34 +01:00
LICENSE Lizenz hinzugefügt: CC BY-NC-SA 4.0 2026-05-06 00:56:48 +02:00
MEHRERE-AQUARIEN.md Migration 1800000000: alte Kopien der Zielwerte, Salz-Kalibrierung und Liter räumen 2026-10-17 09:05:39 +02:00
NAEHRSTOFF-REGLER.md C und Lanthan: ein Schlüssel gilt, Einstellungen springen nicht mehr (Firmware 0.21.1) 2026-11-06 13:10:26 +01:00
README.md Dosenzeiten im Plan Stunde für Stunde wie der ESP: Rampen überstehen die Zeitumstellung 2026-11-06 13:10:26 +01:00

Aquarium Rechner

Werkzeuge für Meerwasser-Aquaristik — von Wasserwechsel-Berechnung bis hin zu vollautomatischer Kalk-Dosierung mit eigener ESP32-Firmware.

Hosting

Selbst gehostet — die Web-Oberfläche wird direkt von einem eigenen PocketBase-Server ausgeliefert (statische Dateien im pb_public/, dazu API + Auth). Es gibt keine zentrale öffentliche Instanz; Details unter Hosting & Daten.

Die einzelnen Rechner liegen unter den Pfaden / (Übersicht), /cr-rechner/, /spurenrechner/, /salz/, /kalk/, /nutrient/, /khtester/, /icp/ und /lager/.

Inhalt

C&R Aquarium Rechner

Berechnet optimale Wasserwechsel mit C&R Lösungen, um ICP-Messwerte schrittweise zu Optimalwerten zu führen. Mit Max-Δ-Begrenzung pro Schritt für schonende Anpassung empfindlicher Korallen. Historie der Messwerte und ausgeführten Ausgleiche mit Verlaufsgrafik.

Spurenelemente Rechner

Plant Tagesdosen einzelner Spurenelemente basierend auf ICP-Messwerten und Verbrauchshistorie. Jede Dosis wird mit Beckenvolumen und Reichweite der Mischung gespeichert — ein Wechsel des ICP-Rhythmus (monatlich/14-tägig) rechnet die Historie deshalb um, statt die alten Millilitermengen weiterzuschreiben. Geregelt wird je Element unterschiedlich: aus den eigenen Messung-Dosis-Paaren schätzt der Rechner, wie viel an einer Abweichung Laborstreuung und wie viel echte Bewegung des Beckens ist, und wendet nur den entsprechenden Teil einer Korrektur an (Spalte γ). Die Schätzung verfeinert sich mit jeder ICP; der Zielwert bleibt derselbe, nur das Tempo passt sich an. Die Schrittweite folgt der engeren Seite des Zielbands, und wenn ein Element mehrere Runden gegen die Dosierung anläuft, benennt der Rechner die Ursache, statt weiter zu regeln. Daten lokal oder im eigenen Account.

Salz & Salinität

Rechnet Dichte, spezifisches Gewicht, Salinität und Leitfähigkeit ineinander um (EOS-80/PSS-78), passt die Salinität gezielt an — in Schritten von höchstens „Max. Abweichung“, je Schritt mit Haken, der die Salinität danach als neuen Stand übernimmt; Wassermengen wahlweise in Liter oder kg (zum Abwiegen) — und kalibriert Salz sowie Spindel. Verfolgt mit Kalkmanagement zusätzlich den Salzzuwachs beim Balling: wie viel Gramm Salz die Ca-, KH- und Mg-Dosierung seit der jüngsten bekannten Salinität (Messung, ICP oder Zurücksetzen auf das Ziel) hinterlassen hat (Chlorid, Natrium, Sulfat bleiben im Wasser; pb_hooks/salz_lib.js, GET /api/salz/dosiert, Selbstcheck jsc tools/test-salz.js) und wie viel Liter gegen Osmosewasser getauscht werden müssen — fällig erst über dem Zielband (Ziel + „Max. Abweichung“), bis dahin mit Termin aus dem Anstieg der letzten 14 Tage. Die geschätzte Salinität (dieser Wert plus Dosierung seitdem) steht vorbelegt unter „Aktuelle Salinität“; eine eigene Eingabe überschreibt sie und wird, als Messung gespeichert, der neue Startpunkt. Wer im C&R-Rechner einen Ausgleich speichert, wird gefragt, ob der Zuwachs zurückgesetzt werden soll.

Lager & Rezepte

Führt den Vorrat an OSCI-Lösungen (Makro, Custom & Repair, Trace, Nutrition) sowie an Pulvern und Salzen. Bestand ist die Summe einer Buchungsliste: Zugänge trägt man selbst ein, Entnahmen buchen die Rechner automatisch — gespeicherte C&R-Ausgleiche, Spurenmischungen, das Auffüllen der Dosierkanister in Kalk- und Nährstoffmanagement (mit Verdünnung, z. B. Lanthan 100 ml/L) und das Anmischen. Die Stärke der OSCI-Lösungen steht an einer Stelle (assets/cr-loesungen.js), die Verdünnung in den Lager-Einstellungen: Daraus rechnet der Server den Dosierplan, der ESP stempelt die Wirkung an jede Dosis. Ändern lässt sich eine Verdünnung nur bei leerem Kanister. Reichweite und Nachbestell-Termin kommen aus dem tatsächlichen Verbrauch: Erhaltung der Pumpen nach Dosierplan (ohne Auto-Dosierung ihr Dosierprotokoll), letzte Spurenmischung, selbst angemischte Lösungen über ihren Rezeptanteil bis zu den Salzen, dazu C&R-Ausgleiche und Meerwasser im Mittel. Rezepte für Calcium, Magnesium, KH-Tag/-Nacht, Meerwasser und C&R aus Salz, in beliebiger Menge. Trace Fluor und C&R Natriumfluorid sind laut OSCI dieselbe Lösung: beide stehen unter ihrer Gruppe, zählen aber als ein gemeinsamer Bestand. Dazu die Wassertests (KH, Calcium, Phosphat HI736/HI774, Nitrat HI781/HI782) in Stück: jeder von Hand gespeicherte Messwert — Startseite, Kalk- oder Nährstoffmanagement — zieht einen Test ab, beim Nitrat und Phosphat den eingestellten Test; ICP-Werte und der KH-Tester nicht. Das gilt erst, wenn der Test einmal gezählt oder gekauft ist, vorher bleibt er ohne Abzug und Erinnerung. Der Verbrauch kommt aus dem üblichen Abstand der Handmessungen. Der Bestand steht in zwei aufklappbaren Bereichen (Lösungen & Salze, Wassertests) mit je eigener Inventur. Die Erinnerung steht auf der Seite und auf der Startseiten-Kachel; dazu kommt sie je Artikel einmal mit der Tagesmail um 8 Uhr (die nächste erst nach dem Zugang bzw. Anmischen). Unter „+“ hat jeder Artikel zwei Haken, beide von Haus aus an: „Bestand überwachen“ (aus = keine Erinnerung, nirgends) und „Erinnerungsmail“ (aus = nur keine Mail).

Nährstoffmanagement (Web + ESP32-Firmware)

Regelt NO₃ und PO₄ über vier Pumpen (Stickstoff, Phosphat, Kohlenstoff, Lanthan). Lernt den Netto-Verbrauch aus der Massenbilanz und leitet daraus eine Erhaltungsdosis samt gerampter Korrektur ab. Die Wahl des Abbaumittels folgt dem molaren N:P-Verhältnis — Kohlenstoff senkt beide Werte, Lanthan wirkt gezielt auf Phosphat.

KH-Tester (Web + ESP32-Firmware)

Misst die Karbonathärte automatisch per Säure-Titration — wahlweise dynamisch bis zum Ziel-pH oder als Gran-Titration mit Regression über den Äquivalenzpunkt. Live-Verfolgung der laufenden Messung im Browser, pH-Kalibrierung mit Sonden-Gesundheitscheck, Überwachung von Säurevorrat und Abwasserbehälter. Ein Klick übernimmt das Ergebnis ins Kalkmanagement, das daraufhin seinen Dosierplan neu rechnet.

Kalkmanagement (Web + ESP32-Firmware)

Komplette Steuerung für eine selbstgebaute 4-Pumpen-Dosier-Anlage (Calcium, Magnesium, KH-Tag, KH-Nacht). Web-Interface plant die Dosierung, ESP32 führt sie aus.

Web-Funktionen:

  • Quick-Inputs für KH/Ca direkt auf der Übersicht + Live-Kanister-Balken
  • Restlaufzeit je Kanister: Schnittpunkt des geplanten Verbrauchs (Ausgleich, Erhaltung, KH Tag/Nacht — wie der ESP dosiert) mit „leer“, ohne Auto-Dosierung aus den letzten 14 Tagen. Gerechnet auf dem Server (pb_hooks/kanister_lib.js, GET /api/kanister) — Anzeige und Warnmail haben dieselben Zahlen
  • Dosier-Plan-Berechnung (KH + Ca/Mg) mit wählbarer Frequenz (2–12 pro Tag) — ohne Messwert als reine Erhaltungsdosierung aus der eingetragenen Verbrauchsrate
  • Verbrauch als Bilanz über die letzten N Messungen (dosiert minus Wertänderung, geteilt durch die Tage) — nur aus einer Messquelle (von Hand oder KH-Tester), ohne ICP-Werte; ein Versatz zwischen zwei Geräten erscheint so nicht als Verbrauch
  • Plan-Visualisierung als Tabelle + Charts
  • Pumpen-Kalibrierung (Live-Lauf über das Web)
  • pH-Sensor-Kalibrierung (2-Punkt mit pH-4 + pH-7)
  • Container-Füllstand-Tracking
  • Historie (Messungen, Dosierungen) mit Charts
  • OTA-Firmware-Update mit einem Klick

ESP32-Firmware:

  • Plan-Cache lokal (NVS) → läuft offline beliebig lange weiter (Anpassungs-Doses anhand absoluter Timestamps, danach unbegrenzte Erhaltungs-Dose)
  • DS3231-RTC-Sync → Dosier-Plan läuft auch nach Stromausfall ohne Internet weiter
  • Auto-Dosierung (per Schalter im Web aktivierbar)
  • Anti-Drip-Sequenz (Prime → Dose → Retract) für sauberes Stop-Verhalten
  • KH-Tag/Nacht-Umschaltung anhand pH-Wert oder Uhrzeit
  • pH-Wächter (optional): eine Sonde, deren Wert 6 h lang steht, gilt als eingefroren → Tag-Pumpe statt Nacht-Lösung, Störung im Gerät-Tab; dazu serverseitig eine E-Mail, wenn der pH ein einstellbares Fenster verlässt oder der ESP die eingefrorene Sonde meldet
  • WS2812-Status-LED zeigt System-Zustand
  • Ausfall-Benachrichtigung per E-Mail — ein serverseitiger Watchdog (PocketBase-Cron) überwacht den Heartbeat und meldet, wenn der ESP länger als 5 Min ausfällt (pro Nutzer im Gerät-Tab an/aus)
  • OTA-Update aus den Releases des eigenen Git-Servers (git.reeftank.pro) — CI baut das .bin automatisch bei jedem Version-Tag

Hosting & Daten

Statische HTML-Seiten, ausgeliefert direkt von PocketBase (pb_public/). Alles läuft im Browser.

Ohne Login (C&R, Spuren): Daten werden ausschließlich lokal im Browser gespeichert (localStorage). Nichts wird übertragen.

Mit Login (E-Mail/Passwort): Daten werden zusätzlich auf einem privaten PocketBase-Server (Deutschland, Übertragung per HTTPS verschlüsselt) abgelegt, damit du sie auf jedem Gerät verfügbar hast. Jeder Nutzer kann nur seine eigenen Daten lesen/schreiben (PocketBase-API-Regeln pro Nutzer). Kein Tracking, keine Weitergabe.

Kalkmanagement, Nährstoffmanagement und KH-Tester erfordern einen Account, weil Web und ESP über PocketBase synchronisieren.

Sicherung je Aquarium: unter „Meine Aquarien“ lädt „Sichern“ alles, was zu einem Aquarium gehört (Einstellungen aller Rechner, Zielwerte, Messwerte, Dosierungen, Pläne, Kalibrierungen, Labor-Proben), als JSON-Datei herunter; „Aquarium hinzufügen → Aus JSON-Sicherung“ legt daraus ein neues Aquarium an. Was dazugehört, fragt der Server bei jedem Aufruf die Datenbank selbst (jede Collection mit Relation auf aquariums, pb_hooks/sicherung_lib.js) — neue Daten sind ohne Änderung mitgesichert. Geprüft mit tools/test-sicherung.py gegen eine lokale PocketBase.

ESP-Firmware bauen

Im Ordner esp-firmware/aquarium-rechner-esp/.

  • Board: ESP32-S3 N16R8 (16 MB Flash, 8 MB OPI PSRAM)
  • IDE: Arduino 2.x mit „ESP32 by Espressif Systems" Boards
  • Partition: 16M Flash (3MB APP/9.9MB FATFS)
  • Libraries: FastAccelStepper, ArduinoJson (v7), RTClib, Adafruit NeoPixel (kein extra Backend-Client nötig — Anbindung an PocketBase per HTTPS-REST)

Eine Firmware für alle Geräte. Welche Aufgabe ein ESP übernimmt, entscheidet seine Rolle (kalk, nutrient, khtest), die im Web-Interface pro Gerät zugewiesen wird — nicht ein eigener Build. Alle drei laufen auf derselben Platine; was die Rolle unterscheidet (Pumpenzahl und -namen, Rührer-PWM beim Tester, pH-Fenster), wird beim Boot anhand der Rolle gesetzt; siehe RoleConfig in config.h.

Neue Releases baut die CI (Forgejo Actions) automatisch: Version-Tag v* pushen → kompilierte .bin erscheint als Release-Asset auf https://git.reeftank.pro — der ESP holt sie sich per OTA. Details in FIRMWARE.md.

Werkzeuge

Alles unter tools/ — wird nicht ins Web gespiegelt (siehe deploy.list).

Seiten vor dem Deploy prüfen. Die Rechner sind je eine HTML-Datei mit einem grossen <script type="module">. Ein Syntaxcheck reicht dort nicht: eine undefinierte Variable in einem const-Literal ist syntaktisch tadellos und zerlegt die Seite trotzdem beim Laden — sichtbar erst, wenn jemand sie aufmacht.

python3 tools/check-inline.py nutrient/index.html

Das Skript löst die Importe heraus, ersetzt sie durch nachgiebige Stubs samt DOM-Attrappe und führt den Modulrumpf aus. Es braucht eine JS-Engine (node oder macOS-jsc) und meldet sichtbar, wenn es keine findet.

tools/deploy.sh ruft es serverseitig vor dem Spiegeln auf: fällt eine Seite durch, bricht der Deploy ab und pb_public bleibt auf dem vorigen Stand.

Lager-Rechnung prüfen. Bestand, Verbrauch aus allen Quellen, Reichweite und die Posten, die die Rechner buchen, gegen ein nachgestelltes Becken. Gerechnet wird nur auf dem Server (GET /api/lager, dieselbe Rechnung wie in der Tagesmail); Lager-Seite und Startseite zeigen sie an:

/System/Library/Frameworks/JavaScriptCore.framework/Versions/Current/Helpers/jsc -m tools/test-lager.mjs

Kanister-Rechnung prüfen. Verbrauch und Restlaufzeit (pb_hooks/kanister_lib.js): Verlauf je Pumpe, Plan mit Ausgleich und Tag/Nacht, Raster der Nährstoff-Pumpen wie in der Firmware, Messplan und Verbrauch je Messung des KH-Testers:

/System/Library/Frameworks/JavaScriptCore.framework/Versions/Current/Helpers/jsc tools/test-kanister.js

Dosen pro Tag: Die Einstellung fließt durch Plan, Kanister-Rechnung, Tagessummen und ESP. tools/test-dosenzahl.mjs hält fest, was bei jeder Zahl und beim Umstellen gleich bleiben muss, und dass jede Dose im Plan in einer Stunde liegt, die der ESP bedient, auch an den Tagen der Zeitumstellung (die Regel steht in assets/dosier-slots.js). Wie der ESP solche Pläne abfährt, prüft der Slot-Test (esp-firmware/test/slots).

TZ=Europe/Berlin /System/Library/Frameworks/JavaScriptCore.framework/Versions/Current/Helpers/jsc -m tools/test-dosenzahl.mjs

Tagesmail durchspielen. Der Server-Hook pb_hooks/container_alert.pb.js (Erinnerung „heute messen" + Kanister fast leer / leer + Lager nachbestellen / anmischen, einmal morgens) läuft nur in der PocketBase-JSVM. Der Selbstcheck stellt sie nach, dreht die Uhr auf 8:07 und prüft Mails und Merker in gut zwanzig Fällen:

/System/Library/Frameworks/JavaScriptCore.framework/Versions/Current/Helpers/jsc tools/test-tagesmail.js

Testvorhersage prüfen. „Nächster Test" (assets/next-test.js) rechnet die Ungenauigkeit des Plans über bis zu vier Messabstände, daraus eine Spanne (früher/später Termin) und wie stabil die Messwerte sind, und kennt den Zustand „Wert außerhalb". Im Eingabefeld steht nur der frühe Termin, der Rest im Fenster beim Darüberfahren. Der Selbstcheck hält Kontrollmessung, Ausreißer, Lücken im Soll-Verlauf, Spanne/Stabilität und die Fälle ohne Dosierung fest:

/System/Library/Frameworks/JavaScriptCore.framework/Versions/Current/Helpers/jsc -m tools/test-vorhersage.mjs

Lokal ansehen. Die Seiten laden ihre Module über absolute Pfade (/assets/...), die ein file://-Aufruf nicht auflöst — ohne Server sieht man deshalb keine Laufzeitfehler, sondern gar nichts.

python3 tools/devserver.py 8788

Danach http://localhost:8788/nutrient/ im Browser. (Bewusst nicht python3 -m http.server: dessen __main__ ruft os.getcwd() auf, was in manchen Sandboxes scheitert.)

Mit Login testen. Der Devserver hat kein PocketBase dahinter — Kalk, Nährstoff, KH-Tester und alles mit Cloud-Sync brauchen eine lokale Instanz:

tools/pb-local.sh

Dieselbe PocketBase-Version wie der Server, die Migrationen und Hooks aus dem Repo, die Seiten direkt aus dem Repo — aber eine eigene, leere Datenbank unter ~/.pb-aquarium/. Beim ersten Start legt das Skript einen Admin und einen verifizierten Testnutzer an (Zugangsdaten in ~/.pb-aquarium/zugang.txt) und leitet Mails ins Leere. Danach http://127.0.0.1:8090/kalk/; mit tools/pb-local.sh reset fängt man von vorn an. Nichts davon erreicht einen echten ESP.

Server-Logik ausrollen. tools/deploy-server.sh prüft vorher die Hooks (tools/check-hooks.js) und spielt alle Migrationen auf einer leeren Datenbank durch; fällt etwas durch, bleibt der Server unangetastet.

Quellcode & Mitmachen

Der Quellcode liegt auf dem eigenen Git-Server: https://git.reeftank.pro (öffentlich lesbar/klonbar).

Lizenz

Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)

Du darfst das Material teilen und bearbeiten, sofern du:

  • Namensnennung vornimmst (Markus / markus629)
  • es nicht für kommerzielle Zwecke nutzt
  • abgeleitete Werke unter der gleichen Lizenz weitergibst

Vollständiger Lizenztext: LICENSE