Posts mit dem Label KI generiert werden angezeigt. Alle Posts anzeigen
Posts mit dem Label KI generiert werden angezeigt. Alle Posts anzeigen

Freitag, 7. August 2026

PowerMgr: Mein selbst gebautes Energie- und Smart-Home-System

PowerMgr: Mein selbst gebautes Energie- und Smart-Home-System

PowerMgr ist mein eigenes Home-Energy-Management-System. Es verbindet Photovoltaik, Batteriespeicher, Wechselrichter, Wärmepumpe, Wetterdaten, Sensoren und Smart-Home-Schnittstellen zu einem lokalen System, das Messwerte sammelt und daraus Steuerentscheidungen ableitet.

Der Kern läuft auf einem kleinen Embedded-Linux-System mit Armbian und Docker. Das ist bewusst unspektakulär: kein proprietärer Smart-Home-Computer, keine komplette Neuverkabelung des Hauses, sondern ein dauerhaft laufender Linux-Rechner, der vorhandene Geräte einbindet und die relevanten Daten an einer Stelle zusammenführt.

Ausgangslage

Beim Hausbau war Smart Home zwar grundsätzlich ein Thema, praktisch fehlten aber viele der Dinge, die später wirklich wichtig wurden. Ein zusätzlicher Smart-Home-Computer hätte mehrere tausend Euro gekostet. Damit wären aber noch keine elektrischen Rollos, Tür- und Fenstersensoren, Heizungs- oder Kühlungssteuerungen und keine sinnvolle Einbindung der Energieanlage vorhanden gewesen.

Später kamen Angebote von Ingenieurbüros dazu, die das Haus für den Betrieb mit Batteriespeicher und Energiemanagement deutlich umfassender umgebaut hätten. Die Größenordnung lag im fünfstelligen Bereich bis etwa 25.000 EUR. Der technische und finanzielle Nutzen passte für mich nicht zusammen: Das Haus hätte teuer umgebaut werden müssen, obwohl viele Geräte bereits vorhanden waren und nur miteinander sprechen mussten.

PowerMgr entstand deshalb aus einem sehr konkreten Ziel: Vorhandene Hardware weiterverwenden, offene oder zumindest lokal kontrollierbare Schnittstellen nutzen und daraus ein System bauen, das zum realen Haus passt.

Warum Eigenbau?

Das Problem war nicht, dass es keine Smart-Home-Produkte gab. Das Problem war, dass die verfügbaren Lösungen die eigentlichen Energiefragen nicht gut genug beantworteten.

Für mich ging es nicht darum, eine Lampe per App einzuschalten. Das System sollte verstehen, wann Energie erzeugt, gespeichert, verbraucht oder ins Netz eingespeist wird. Daraus sollten Entscheidungen entstehen:

  • Soll die Batterie geladen oder entladen werden?
  • Ist genug PV-Leistung übrig, um die Kühlung zu starten?
  • Muss die Lüftung laufen, weil die Luft im Haus schlecht ist?
  • Soll eine Fahrzeugladung freigegeben, gedrosselt oder gestoppt werden?
  • Sind Türen oder Fenster offen, obwohl die Kühlung aktiv werden soll?
  • Welche Daten müssen in HomeKit, Grafana oder einer mobilen App sichtbar sein?

Dafür war ein klassisches Smart-Home-System zu oberflächlich. Ein reines Energiemonitoring hätte dagegen nur angezeigt, was passiert, aber nicht aktiv gesteuert. PowerMgr sitzt genau dazwischen: Es ist kein universelles Smart-Home-Framework, sondern eine lokale Steuerung für das eigene Haus und die eigene Energieanlage.

Systemüberblick

PowerMgr ist ein Python-Projekt mit Docker-Betrieb. Im Repository liegen unter anderem ein Dockerfile, eine docker-compose.yml, Konfigurationsdateien, ein Webinterface, dynamische Regeldateien und Module für die angebundenen Geräte.

Die wichtigste Struktur ist nicht eine einzelne große Steuerdatei, sondern die Trennung nach Aufgaben:

  • powermgr.py startet den Hauptprozess.
  • lib/ enthält Geräteanbindungen und gemeinsame Infrastruktur.
  • dynamic/ enthält Regeldateien, die im Betrieb ausgewertet werden.
  • dynamic_threads/ enthält länger laufende Regelpfade, zum Beispiel für die ESS-Leistungssteuerung.
  • html/ stellt Webinterface und Statusseiten bereit.
  • conf/ enthält Beispielkonfiguration und Betriebsparameter.

Die dynamischen Regeldateien werden nach ihrem dreistelligen Präfix sortiert ausgeführt. Dadurch ist der Ablauf im Betrieb nachvollziehbar: erst Grunddaten laden, dann Gesundheitszustände bewerten, Wetter und Homebridge-Status einlesen, anschließend Proxon, Shelly, EVCC und andere Steuerpfade behandeln.

Eingebundene Geräte und Datenquellen

PowerMgr bindet mehrere sehr unterschiedliche Systeme zusammen.

Die Photovoltaikseite wird unter anderem über einen StecaGrid-Wechselrichter ausgelesen. Das Modul lib/stecagrid.py liest die aktuelle AC-Leistung und schreibt die Daten für die spätere Auswertung nach InfluxDB.

Der Batteriespeicher wird über einen Victron MultiPlus II und Pylontech-Batterien eingebunden. Das Modul lib/energy_storage.py liest Inverter- und Batteriedaten, überwacht Zustände und stellt Funktionen bereit, um Lade- und Entladeleistungen zu setzen.

Die Zimmermann Proxon FTW-2 wird angezeigt und gesteuert. PowerMgr kann Betriebsart, Kühlung, Lüftung, Heizelemente und weitere Zustände berücksichtigen. Die Regeln dafür liegen unter anderem in dynamic/070-proxon-timed.py, dynamic/080-proxon.py und dynamic/090-proxon-t300.py.

Wetterdaten kommen aus einer eigenen Wetterstation, optionalen Oko-Wetterstation-Sensoren und OpenWeather. Das ist wichtig, weil Energieentscheidungen im Haus nicht nur vom aktuellen Stromwert abhängen. Für Kühlung und Lüftung spielen Außentemperatur, Tagesmaximaltemperatur, Raumtemperaturen und verfügbare PV-Leistung zusammen.

Zusätzlich sind Homebridge, Shelly-Geräte, Tür-/Fenstersensoren und EVCC.io angebunden. Dadurch werden Hauszustände, manuelle Freigaben und Fahrzeugladung Teil derselben Entscheidungslogik.

Vom Messen zum Steuern

PowerMgr sammelt nicht nur Daten. Das System entscheidet im Betrieb, ob eine Aktion sinnvoll ist.

Ein einfaches Beispiel ist die Kühlung. Wenn genug PV-Leistung verfügbar ist, die Außentemperatur hoch genug ist, die Tagesprognose passt, Türen und Fenster geschlossen sind und die Proxon in der passenden Betriebsart läuft, kann PowerMgr die Kühlung einschalten. Wenn die Batterie gerade lädt, kann diese Ladeleistung je nach Konfiguration als verfügbare Leistung mitgezählt werden. Wenn die Batterie entlädt, kann die Kühlung unter bestimmten Komfort- und SoC-Grenzen weiterlaufen oder durch Batterie-Fallback unterstützt werden.

Das ist der entscheidende Unterschied zu einer starren Zeitsteuerung. Die Anlage reagiert auf Hauszustand, Energiefluss und Komfortbedingungen.

Betrieb und Beobachtbarkeit

Der Betrieb ist lokal und nachvollziehbar aufgebaut. Das Webinterface zeigt Statusdaten, Konfiguration und Diagnoseinformationen. Zusätzlich schreibt PowerMgr Messwerte nach InfluxDB, sodass sie in Grafana ausgewertet werden können.

Für Steuerentscheidungen gibt es ein eigenes Decision-Logging. Neben dem normalen Textlog hält PowerMgr strukturierte Ereignisse im Speicher und stellt sie über diese Endpunkte bereit:

/decision_log
/decision_log.json

Damit lässt sich später sehen, was passiert ist und warum es passiert ist. Bei der Kühlung kann zum Beispiel sichtbar werden, ob PV-Überschuss, Batterieunterstützung, geöffnete Fenster, Wallbox-Ladung oder Temperaturgrenzen die Entscheidung beeinflusst haben. Bei der Batterie wird sichtbar, welcher Zielwert berechnet wurde und welche Eingangsgrößen beteiligt waren.

Ergebnis

Der praktische Nutzen liegt in der Eigenverwendung des erzeugten Stroms. Zu Beginn lag die eigene Nutzung der PV-Erzeugung nur grob bei 10 bis 15 Prozent. Im aktuellen Ausbau liegt sie nach eigener Messung bei etwas über 70 Prozent.

Das ist kein abstrakter Optimierungswert. Es bedeutet, dass mehr selbst erzeugter Strom im Haus bleibt: für Grundlast, Batterie, Kühlung, Lüftung, Heizelemente oder Fahrzeugladung. Gerade bei niedriger Einspeisevergütung ist das wichtiger als eine möglichst schöne Smart-Home-Oberfläche.

PowerMgr ist deshalb für mich weniger ein Smart-Home-Projekt im klassischen Sinn. Es ist ein lokales Energie- und Betriebsleitsystem für ein konkretes Haus.

Freitag, 31. Juli 2026

Lumini P30 Control: China-Lampe mit diyHue steuerbar machen

Lumini P30 Control: China-Lampe mit diyHue steuerbar machen

Lumini P30 Control ist ein Umbau einer kleinen Aquarium-LED-Lampe, die unter Bezeichnungen wie Lumini, Lominie, Pixie 30 und P30 verkauft wurde. Die Lampe selbst passte gut zu einem kleinen Meerwasserbecken. Das optionale Steuermodul des Herstellers war dagegen teuer und für diesen Zweck kaum brauchbar: kein WLAN, keine gezielten eigenen Einstellungen und nur vorgefertigte Programme, die nicht zum Becken passten.

Der konkrete Einsatz war ein 50-Liter-Nano-Meerwasseraquarium mit Makroalgen, Riffkeramik, Einsiedlern und Schnecken. Die Beleuchtung war dafür grundsätzlich geeignet. Statt die Lampe zu ersetzen, wurde die vorhandene Elektronik so erweitert, dass die vier LED-Kanäle per ESP8266, PWM und eigenem Webinterface steuerbar wurden. Zusätzlich blieb die Anbindung an diyHue erhalten, damit die Lampe aus Sicht von Hue, HomeKit oder Siri wie ein Hue-kompatibles Gerät verwendet werden konnte.

Das Projekt war abgeschlossen und lief etwa sechs Monate im realen Aquarium-Betrieb. Abgebaut wurde später das Aquarium, nicht wegen der Lampe, sondern weil das kleine Meerwasserbecken insgesamt nicht stabil genug lief.

Ausgangslage

Die Lampe war eine typische günstige Aquariumleuchte aus dem Amazon-Umfeld. Technisch war sie interessant, weil intern getrennte LED-Kanäle vorhanden waren. Praktisch fehlte aber eine brauchbare Steuerung für einen eigenen Tagesverlauf. Für ein kleines Meerwasserbecken ist gerade die Lichtsteuerung wichtig, weil ein abruptes Ein- und Ausschalten oder unpassende Spektren schnell sichtbar werden.

Das Hersteller-Steuermodul löste dieses Problem nicht gut genug. Es bot keine WLAN-Integration und keine freie Konfiguration der einzelnen Kanäle. Deshalb entstand ein eigener Controller, der die Lampe elektrisch direkt ansteuert und die Bedienung ins Heimnetz verlagert.

Warum Eigenbau?

Elektrisch war der Umbau überschaubar: Die LED-Kanäle der Lampe lassen sich über PWM steuern, indem die Steuerleitungen über MOSFET-Module nach GND gezogen werden. Die eigentliche Arbeit lag deshalb weniger in komplizierter Leistungselektronik, sondern in der Firmware: mehrere Kanäle, ein konfigurierbarer Tagesplan, lokale Bedienung im Webinterface und die Kompatibilität zur vorhandenen diyHue-Welt mussten zusammenpassen.

Als Basis diente der diyHue-Sketch ESP8266/Generic_Dimmable_Light. Dieser brachte die Hue-kompatible Erkennung und die /state-Schnittstelle bereits mit. Lumini P30 Control behielt diese Schnittstellen bei, baute den Sketch aber zu einer auf die Lampe zugeschnittenen Firmware um.

Das war auch eines der ersten Projekte, bei denen massiv ChatGPT im Stand von 2023 eingesetzt wurde. In der Projekt-README steht entsprechend, dass ein großer Teil des Codes mit ChatGPT erzeugt und anschließend selbst angepasst wurde.

Hardware

Der Controller ist ein alter NodeMCU v1.0 auf ESP8266-Basis. Die vier Lampenkanäle werden über vier D4184-MOS-Breakoutboards geschaltet. Die Versorgung des NodeMCU erfolgt über einen 7805-Regler: dessen Eingang hängt an den 24 V des Lampen-Netzteils, der Ausgang am Vin-Pin des NodeMCU.

Die Verbindung zur Lampe wurde über ein passendes Anschlusskabel hergestellt, das halbiert und auf die MOSFET-Boards geführt wurde. Die Pinbelegung ist im Projekt dokumentiert:

Kanal LED-Farbe Kabelfarbe MOS-Board NodeMCU-Pin GPIO
ch1 blau blau 1 D1 GPIO5
ch2 warmweiß schwarz 2 D2 GPIO4
ch3 violett rot 3 D7 GPIO13
ch4 weiß, rot und grün weiß 4 D5 GPIO14
Versorgung +24 V grün - - -

Die Pinbelegung war am Anfang einer der unsicheren Punkte. Der Projektkontext verweist deshalb auf einen Reef2Reef-Thread zur Lumini/Lominie Pixie 30/P30, in dem der Umbau und die Leitungen ebenfalls behandelt werden:

https://www.reef2reef.com/threads/for-lumini-lominie-pixie-30-p30-hers-how-to-add-ramp-up-down-and-timer-with-memory-quite-cheaply.935409/

Der erste Prototyp ist im Reef2Reef-Thread mit zwei Bildern dokumentiert. Zu sehen sind der NodeMCU-Aufbau mit den MOSFET-Boards und die laufende Lampe am Nano-Becken:

Erster Lumini-P30-Controller-Prototyp mit NodeMCU, vier MOSFET-Boards und Verkabelung

Lumini P30 am Nano-Meerwasseraquarium im Betrieb

Im Projekt liegen außerdem ein Schaltbild des Controllers und Fotos eines späteren 3D-gedruckten Gehäuses.

Software

Die Firmware ist ein Arduino-/ESP8266-Projekt. Im Vergleich zum ursprünglichen diyHue-Beispiel wurde der Code auf mehrere Dateien aufgeteilt:

  • firmware.ino: Setup, WLAN, EEPROM, SPIFFS, HTTP-Update und Hauptloop
  • light_engine.ino: PWM-Berechnung, Szenen und Helligkeitsübergänge
  • timing_control.ino: NTP-Zeit, Tagesplan und EEPROM-Daten für zehn Zeitpunkte
  • webserver.ino: lokale HTTP-Endpunkte und Weboberfläche
  • test_pwm.ino: Testlauf durch die vier PWM-Kanäle
  • firmware/html/ und firmware/data/: HTML-, CSS- und JavaScript-Dateien für das Webinterface

Die diyHue-Kompatibilität blieb dabei erhalten. Die Firmware antwortet weiterhin auf /detect mit einem native_multi-Gerät und auf /state mit den Helligkeits- und Ein/Aus-Zuständen der einzelnen Kanäle. Dadurch kann sie von diyHue und darüber indirekt auch von Hue-Apps oder HomeKit-Integrationen genutzt werden.

Funktionsweise

Nach dem Start verbindet sich der NodeMCU per WLAN. Die IP-Adresse kann dynamisch per DHCP vergeben oder im Webinterface statisch konfiguriert werden. Die Weboberfläche wird aus SPIFFS-Dateien geladen; die HTML-Dateien werden vor dem Upload aus Templates erzeugt.

Für die Lichtsteuerung gibt es zwei Ebenen. Die Hue-kompatible Ebene setzt pro Kanal Ein/Aus und Helligkeit über JSON an /state. Die lokale Ebene bietet ein Webinterface mit separaten Reglern für die vier Kanäle, Statusanzeige der tatsächlichen PWM-Werte, Szenen, Startverhalten, Netzwerkdaten und einem Editor für den Tagesverlauf.

Der Tagesverlauf besteht aus zehn Zeitpunkten. Jeder Datenpunkt enthält Stunde, Minute und die Helligkeitswerte für ch1 bis ch4. Die Firmware liest die Zeit über NTP, speichert die Timing-Daten im EEPROM und berechnet zwischen zwei Datenpunkten Übergänge. Dadurch kann die Lampe morgens hoch- und abends wieder herunterdimmen, ohne dass dauerhaft ein externer Server die Werte schicken muss.

Die PWM-Frequenz ist im Projekt auf 500 Hz gesetzt. Anfangs gab es Flackern durch unpassende PWM-Einstellungen; dieser Punkt wurde im Projektverlauf behoben. Die Firmware begrenzt die PWM-Werte auf den Bereich 0 bis 255 und rechnet die Helligkeitswerte über eine eigene calcPWM()-Funktion auf die Ausgabe um.

Bedienung

Im normalen Betrieb wurde die Lampe per WLAN ins Heimnetz eingebunden und über das Webinterface konfiguriert. Dort konnten die Kanäle einzeln geschaltet und gedimmt, der Tagesplan bearbeitet, Timing-Control aktiviert oder deaktiviert und ein PWM-Test gestartet werden.

Zusätzlich blieb die Bedienung über die Hue-Welt möglich. Mit diyHue konnte die Lampe wie ein Hue-kompatibles Gerät erscheinen. Wenn diese Hue-Integration über ein Homebridge-Plugin nach HomeKit weitergereicht wurde, ließ sich die Lampe auch per Siri steuern.

Für Tests gibt es außerdem das Skript lp3ctrl.sh. Es fragt die vier Kanalzustände über /state?light=... ab und kann per HTTP-PUT einen Kanalzustand mit Helligkeit setzen. Das Skript ist eher ein Diagnosewerkzeug als die eigentliche Bedienoberfläche.

Build und Installation

Die README dokumentiert keinen vollständigen modernen Build-Prozess, aber den historischen Upload-Weg:

  1. Firmware mit der Arduino-ESP8266-Umgebung auf den NodeMCU schreiben.
  2. HTML-Dateien für SPIFFS erzeugen:
bash ../../tools/html_gen_files.sh
  1. Die erzeugten Dateien in den data-Ordner legen.
  2. Den SPIFFS-Inhalt mit dem ESP8266 Sketch Data Upload Plugin der alten Arduino IDE hochladen.
  3. Nach dem ersten Start im Webinterface reset timing control data ausführen.

Die README weist ausdrücklich darauf hin, beim Flashen den EEPROM zu löschen. Die Firmware setzt Standardwerte für die Konfiguration, behandelt den Timing-Datenblock aber gesondert.

Stolpersteine

Die Pinbelegung war zunächst nicht offensichtlich. Ohne die dokumentierte Zuordnung der Kabelfarben und GPIOs lässt sich der Umbau leicht falsch verdrahten.

Die PWM-Einstellungen waren ein praktischer Testpunkt. Eine ungeeignete Frequenz führte anfangs zu sichtbarem Flackern; in der dokumentierten Firmware ist PWM_FREQ auf 500 Hz gesetzt.

Der Build-Prozess hängt an der damaligen Arduino-ESP8266-Werkzeugkette und am alten ESP8266 Sketch Data Upload Plugin. Der Artikel ist deshalb keine aktuelle Schritt-für-Schritt-Anleitung für heutige Arduino-IDE-Versionen.

Die Weboberfläche nutzt JavaScript-Bibliotheken von öffentlichen CDNs. Für den Betrieb im Heimnetz war das ausreichend, macht die Oberfläche aber nicht vollständig unabhängig vom Internet, solange diese Dateien nicht lokal eingebunden werden.

Projektstand

Lumini P30 Control liegt im lokalen Archiv unter oko_git_backup/lumini_p30_control. Das Projekt enthält eine Okoyono-Gitea-Remote-URL, die beim Prüfen für diesen Artikel aber nicht öffentlich erreichbar war. Deshalb wird hier kein direkter Repository-Link veröffentlicht.

Der Stand ist abgeschlossen und historisch. Die Lampe hat im realen Nano-Meerwasseraquarium etwa sechs Monate funktioniert. Der Umbau zeigt damit vor allem, dass die P30-Hardware mit einem ESP8266, vier MOSFET-Kanälen und angepasster diyHue-Firmware gut steuerbar war. Weitergeführt wurde das Projekt nach dem Abbau des Aquariums nicht.

Die ältere DIYHue Lights-Dokumentation gehört fachlich zu diesem Artikel: Sie beschreibt den Upstream-Fundus, aus dem die verwendete Basis stammt. Als eigener Blogpost wäre sie neben Lumini P30 Control eher eine Doppelung.

Freitag, 24. Juli 2026

USB2SerialMux - Weniger Kabelsalat beim Debuggen von Embedded-Systemen

USB2SerialMux - Weniger Kabelsalat beim Debuggen von Embedded-Systemen

USB2SerialMux ist ein kleines Hardware-/Firmware-Projekt, um mehrere USART-faehige Geraete ueber einen einzigen USB-Anschluss erreichbar zu machen.

USB2SerialMux PCB Top-Seite

Der konkrete Anlass war ein alter Embedded-Cluster. Darin liefen mehrere Orange Pis, und beim Booten wollte ich nicht nur einen einzelnen Knoten sehen, sondern zwischen den seriellen Konsolen der Boards umschalten koennen. Vorher bedeutete das: ein USB-Hub, mehrere USB-zu-Serial-Adapter, viele Kabel und am Ende trotzdem die Frage, welcher Adapter gerade zu welchem Board gehoert. Danach hing ein USB-Pigtail an meiner Platine und die Zielgeraete wurden per Multiplexer ausgewaehlt.

Das Projekt ist kein grosses Framework und auch kein universeller Console-Server. Es ist eine pragmatische Loesung gegen serielles Kabelchaos.

Was das Problem war

Bei Embedded-Boards ist die serielle Konsole oft der ehrlichste Debug-Ausgang. Gerade beim Booten sieht man dort Dinge, die spaeter ueber SSH oder Netzwerk nicht mehr sichtbar sind:

  • Bootloader-Ausgaben
  • Kernel-Start
  • fruehe Fehler vor dem Netzwerkstart
  • Login-Konsole
  • sporadische Ausgaben im Betrieb

Mit einem einzelnen Board ist das einfach: USB-Serial-Adapter anschliessen, screen, minicom oder picocom starten und mitlesen. Bei sieben oder acht Boards wird daraus aber schnell ein unuebersichtlicher Aufbau. Jeder Adapter erzeugt ein eigenes Device, die Reihenfolge kann sich aendern, der USB-Hub liegt irgendwo zwischen den Boards, und beim Mitschneiden muss man immer wissen, welcher Port gerade welches Geraet ist.

USB2SerialMux loest nicht alle Probleme gleichzeitig. Es reduziert das Setup bewusst auf eine klare 1-zu-1-Verbindung: ein USB-Anschluss am Rechner, ein gerade ausgewaehlter USART-Kanal auf der Zielseite.

Wie die Loesung aufgebaut ist

Die Platine basiert auf einem ATmega32U4 mit LUFA-Firmware. Am Rechner meldet sich das Geraet als USB-CDC-Device mit zwei virtuellen seriellen Interfaces:

  • ein Control-Interface fuer Kommandos wie Kanalwahl, Baudrate abfragen oder Baudrate setzen
  • ein Daten-Interface fuer den eigentlichen USART-Datenstrom

Auf der Hardwareseite schalten zwei 74HCT4051-Multiplexer die USART-Leitungen auf einen von acht Kanaelen. Die Firmware steuert die drei MUX-Select-Leitungen und leitet die Daten zwischen USB-CDC und UART weiter.

Das ist der wichtige Punkt: Es ist kein USB-Hub mit mehreren USB-Serial-Adaptern. Es ist auch kein paralleler Mehrkanal-Logger. Der Host sieht ein USB-Geraet, und die Platine verbindet dieses logisch mit genau einem ausgewaehlten USART-Ziel.

Bedienung

Nach dem Einstecken wird das Board als serielles USB-Geraet erkannt. Die Steuerung passiert ueber das Python-Tool im Projekt:

python tools/muxctrl.py -d /dev/ttyACM0 -l 3 -m

Damit wird zum Beispiel MUX-Kanal 3 ausgewaehlt und der aktuelle Kanal wieder abgefragt. Die Firmware unterstuetzt Kanaele von 0 bis 7.

Die Baudrate kann ebenfalls ueber das Tool gesetzt werden:

python tools/muxctrl.py -d /dev/ttyACM0 -s 115200 -b

Im Projekt liegt ausserdem ein kleines Shell-Skript, das den urspruenglichen Cluster-Anwendungsfall zeigt: tools/logClusterBootup.sh setzt Default-Werte, startet ein Logging-Skript und schaltet dann nacheinander durch die Kanaele 0 bis 7.

Warum das fuer den Cluster praktisch war

Vorher sah das Setup ungefaehr so aus:

  • mehrere Orange Pis
  • je Board ein USB-Serial-Adapter
  • ein USB-Hub
  • viele kurze Adapter- und Dupont-Kabel
  • manuelle Zuordnung von /dev/ttyUSB* oder /dev/ttyACM*

Nachher war der Aufbau deutlich ruhiger:

  • ein USB-Kabel zum Rechner
  • eine kleine Platine am Cluster
  • bis zu acht USART-Anschluesse auf der Zielseite
  • Umschalten per Kommandozeile

Fuer meinen Zweck war das genau die richtige Vereinfachung. Beim Booten konnte ich Kanal fuer Kanal mitloggen oder gezielt auf den gerade interessanten Knoten schalten. Im laufenden Betrieb war die serielle Konsole weiterhin erreichbar, ohne jedes Mal Kabel oder Adapter umzustecken.

Warum ueberhaupt eine eigene Platine?

Damals haette ich das Problem natuerlich auch mit mehreren USB-zu-Serial-Adaptern loesen koennen. Technisch waere das vollkommen ausreichend gewesen.

Mich reizte jedoch die Idee, dafuer eine eigene Hardware zu entwickeln. Zum einen entstand dadurch ein wesentlich aufgeraeumterer Aufbau. Zum anderen bot das Projekt die Moeglichkeit, Mikrocontroller-Firmware, USB-Kommunikation, Leiterplattenentwicklung und Embedded-Hardware in einem kleinen, ueberschaubaren Projekt miteinander zu verbinden.

Rueckblickend war genau das vermutlich der eigentliche Grund, warum dieses Projekt entstanden ist.

Hardware

Aus den Projektdateien ist dieser Aufbau ableitbar:

  • Mikrocontroller: ATmega32U4-A
  • USB-Anschluss: USB Mini-B
  • Multiplexer: 2 x 74HCT4051
  • Firmware-Basis: LUFA CDC
  • Takt: 16 MHz laut Firmware-Makefile
  • Ziel: acht umschaltbare USART-Kanaele

Die Platine ist als Shared Project bei OSH Park verfuegbar: USB2SerialMux bei OSH Park.

Das groesste praktische Problem war nicht die Firmware, sondern die Platine: moeglichst klein bleiben und trotzdem so viele USART-Anschluesse wie moeglich sauber herausfuehren. Genau an der Stelle wird so ein Projekt mechanisch und layoutseitig interessant. Die reine Idee ist simpel, aber auf engem Raum mit USB, Mikrocontroller, Multiplexern und Anschluessen wird es schnell ein echtes PCB-Projekt.

Firmware

Die Firmware ist ein angepasstes LUFA-CDC-Beispiel. Im Quellcode ist der Stand mit 08/2016 und Version v0.1 kommentiert; auf der Platine steht USB2SerialMux v0.2.

Sie stellt auf der USB-Seite zwei CDC-Interfaces bereit: eines fuer die Steuerung und eines fuer den eigentlichen seriellen Datenstrom. Die Firmware nimmt die Kommandos des Python-Tools entgegen, schaltet darueber den aktiven MUX-Kanal und reicht die UART-Daten zwischen Host und ausgewaehltem Zielgeraet weiter. Die Baudrate wird dabei im EEPROM gespeichert, und fuer Firmware-Updates kann das Board per Kommando in den Bootloader springen.

Das Makefile ist fuer atmega32u4 ausgelegt und nutzt dfu-programmer zum Flashen. Vor dem Programmieren kann das Board ueber muxctrl.py in den Bootloader geschickt werden.

Was es nicht kann

USB2SerialMux ist bewusst kein Mehrkanal-Logger. Es kann nicht zwei oder mehr USART-Geraete gleichzeitig mitschneiden. Es gibt immer genau eine aktive Verbindung zwischen USB-Seite und einem Zielkanal.

Das ist keine versteckte Einschraenkung, sondern die eigentliche Designentscheidung. Fuer paralleles Logging aller Boards waere ein anderes Design noetig: mehrere UARTs, groesserer Controller, anderes Buffering, anderes Host-Protokoll. Fuer meinen Anwendungsfall war das nicht der Punkt. Ich wollte das serielle Chaos am Cluster reduzieren und bei Bedarf sauber umschalten koennen.

Repository

USB2SerialMux auf Okoyono-Gitea

Fazit

USB2SerialMux ist ein typisches Werkstattprojekt: ein konkretes Problem, eine kleine Platine, etwas Firmware und am Ende weniger Kabelsalat. Es ersetzt keinen Console-Server und keinen Log-Aggregator, aber es macht einen bestimmten Embedded-Alltag deutlich angenehmer: viele USART-Geraete, ein USB-Anschluss, Umschalten per Kommandozeile.

Fuer mich war das der Punkt, an dem aus sieben oder acht USB-Serial-Adaptern an einem Hub eine kleine eigene Platine wurde.

Dienstag, 14. Juli 2026

Blogger Auto Poster: Aus einem Workspace automatisch Blogposts vorbereiten

Blogger Auto Poster

Zweck

Dieses Projekt ist entstanden, um aus vielen vorhandenen lokalen Projekten automatisch strukturierte Markdown-Dateien zu machen und daraus eine Blogger-Queue für klautesblog.blogspot.com aufzubauen. Die Dateien sollen nicht direkt blind veröffentlicht werden, sondern zuerst als geparkte Markdown-Posts im Backlog vorliegen. Danach kann ein Linux-Server in einem festen Intervall jeweils den nächsten Post aus der aktiven Queue hochladen.

Das eigentliche Ziel ist nicht nur ein Upload-Script. Der wichtige Teil ist der Workflow davor: Ein Workspace wird rekursiv analysiert, Projekte werden fachlich eingeordnet, uninteressante Dateien werden ausgeschlossen, relevante Projekte bekommen Story, Ziel, Labels und ein sauberes Markdown-Format.

Ausgangslage

In meinem Entwicklungsordner lagen viele kleine und größere Projekte: Smart-Home-Energiemanagement, Aquarium-Technik, Amateurfunk-Hardware, Homebridge-Integrationen, ESP32/ESP8266-Hacks, alte Software-Fixes und Tabletop-/Mordheim-Material.

Viele dieser Projekte waren technisch interessant, aber nicht direkt als Blogpost nutzbar. Es fehlte eine einheitliche Struktur:

  • Was war das Problem?
  • Warum wurde das Projekt angefangen?
  • Was war das konkrete Ziel?
  • Welche Hardware und Software gehören dazu?
  • Ist das Projekt wirklich postbar?
  • Welche Labels passen später in Blogger?
  • Welche Dateien sollen ignoriert werden?

Grundidee

Der Ablauf besteht aus zwei getrennten Schritten:

  1. Codex analysiert den Workspace und erzeugt Markdown-Dokumentation.
  2. Der Blogger Auto Poster nimmt freigegebene Markdown-Dateien und lädt sie in festen Intervallen zu Blogger hoch.

Diese Trennung ist wichtig. Die Analyse darf ruhig interaktiv sein, weil Projektkontext oft nur im Kopf vorhanden ist. Der Upload soll dagegen langweilig und deterministisch laufen.

Prompt 1: Workspace rekursiv analysieren

Der erste Prompt beschreibt den Analyseauftrag. Er soll nicht sofort posten und auch keine Projektdateien verändern, sondern nur Dokumentation erzeugen.

Analysiere den aktuell geöffneten Workspace rekursiv.

Ziel:
- Finde alle relevanten Projekte.
- Erstelle pro Projekt eine Markdown-Datei im Ordner output/.
- Ändere keine bestehenden Projektdateien.
- Poste nichts automatisch.
- Beschreibe Zweck, Hardware, Software, Aufbau, Build, Konfiguration,
  Verwendung, Schnittstellen, Stolpersteine und offene Punkte.
- Kennzeichne Unsicherheiten klar.
- Dokumentiere keine Secrets, Tokens, privaten IPs oder Passwörter.

Damit entsteht zuerst eine technische Rohdokumentation. Sie ist noch kein fertiger Blogpost, aber sie macht sichtbar, welche Projekte es überhaupt gibt.

Prompt 2: Projekte fachlich bewerten

Danach folgt die Frage, welche Dateien für einen Blog interessant sind. Dabei geht es nicht um perfekte Texte, sondern um eine harte Vorauswahl.

Prüfe alle erzeugten Markdown-Dateien.

Ziel:
- Welche Dateien sind als einzige Posts auf klautesblog.blogspot.com interessant?
- Welche passen zu einem technischen Blog?
- Welche sind eher nicht interessant?
- Nichts posten und nichts extern ändern.
- Liste klar auf, welche Dateien passen und welche nicht.
- Die Story dahinter darf noch fehlen; das ist ein eigener Schritt.

Dieser Schritt trennt technische Artefakte von echten Blog-Kandidaten.

Prompt 3: Upstream-Projekte und Quellen prüfen

Viele kleine Projekte basieren auf fremden GitHub-Repositories, Schaltplänen, YouTube-Videos oder bestehenden Bibliotheken. Das muss sauber in die Dokumentation.

Prüfe bei welchen Projekten ein bestehendes Projekt eines anderen
auf GitHub oder eine andere externe Quelle als Basis genommen wurde.

Wenn das in der Dokumentation fehlt:
- Ergänze einen Hinweis auf Basis/Upstream.
- Mache klar, was eigenes Projekt ist und was nicht.
- Verlinke das Original, wenn es erkennbar ist.
- Ändere nur die erzeugten Dokumentationsdateien.

Das ist wichtig, weil ein Blogpost sonst schnell so wirkt, als sei alles komplett selbst entwickelt worden.

Prompt 4: Entstehung und Ziel interaktiv ergänzen

Die technische Analyse allein reicht nicht. Ein Projekt wird erst durch die Entstehungsgeschichte interessant.

Frage mich zu jedem relevanten Projekt:
- Warum habe ich dieses Projekt angefangen?
- Welches konkrete Problem sollte gelöst werden?
- Was war das Ziel?
- Was ist das Ergebnis oder der aktuelle Status?

Füge diese Angaben in die jeweilige Markdown-Datei im output-Ordner ein.

Ein Beispiel dafür ist PowerMgr.

Beispiel: PowerMgr

Die reine Codeanalyse erkennt ein Python-/Docker-Projekt für Energiemanagement. Der wichtige Blogwert steckt aber in der Geschichte dahinter:

  • Es sollte ein Energiemanagement entstehen, das vorhandene Geräte weiter nutzt.
  • Eingebunden wurden unter anderem StecaGrid-PV-Wechselrichter, Zimmermann Proxon FTW-2, Shelly-Geräte, DIY-Wetterstation, OpenWeather, ESP32-Geräte und EVCC.io.
  • Angebote von Ingenieurbüros lagen bei etwa 15.000 bis 25.000 EUR für einen Umbau des Hauses.
  • Das eigene System bindet einen Victron Multiplus ein.
  • Ergebnis: etwa 50 Prozent weniger Stromkosten und etwa 70 Prozent Eigenverbrauch der PV-Erzeugung.

Aus einer technischen Datei wird dadurch ein nachvollziehbarer Artikel: Problem, Eigenbau, Integration, Ergebnis.

Prompt 5: Ignorierte Projekte verschieben

Nicht alles soll in die Blogqueue. Manche Projekte waren nur Tests, Sackgassen oder reine Fremdsoftware.

Alles, was ich als "ignorieren" markiert habe,
verschiebe in output/ignore.

Diese Dateien sollen erhalten bleiben, aber nicht als Blogpost-Kandidaten gelten.

Im Auto-Poster bleibt dieser Mechanismus erhalten: posts/queue/ignore/ wird vom Upload-Script übersprungen.

Prompt 6: Neues Auto-Poster-Projekt erzeugen

Aus der analysierten Dokumentation wurde danach ein eigenes Projekt gebaut.

Erstelle ein neues Projekt für einen Blogger Auto Poster.

Anforderungen:
- Dockerfile
- docker-compose.yml
- Upload-Script
- Config-Datei für Blogger und Input-Ordner
- Shared Input-Folder im Docker Compose Setup
- Post-Intervall in der Config
- Bereits erledigte Markdown-Dateien nach done/ verschieben
- output-Ordner in das neue Projekt verschieben und umbenennen
- Neues Git-Repository initialisieren
- Markdown-Dateien mit Labels und sauberem Post-Format vorbereiten

Das Ergebnis ist dieses Repository.

Umsetzung im Projekt

Aus dem ersten Upload-Script ist inzwischen ein kleines, klar getrenntes Tooling-Projekt geworden. Die wichtigste Änderung ist die Aufteilung nach Verantwortlichkeiten: Benutzereingabe, Markdown-Logik, Blogger-API, lokale State-Datei, Zeitplanung und Docker-Runtime liegen nicht mehr vermischt in einem Script.

Der nachbaubare Stand des Tools liegt öffentlich auf GitHub: klaute/blogger-auto-poster.

Dieses öffentliche Repository enthält nur das Tooling, eine Beispielkonfiguration, einen neutralen Beispielpost und die Setup-Anleitung. Die echten Blogpost-Entwürfe, lokale State-Dateien, OAuth-Konfigurationen und Tokens bleiben im privaten Arbeitsverzeichnis.

Die aktuelle Projektstruktur sieht so aus:

config/
  config.example.yml
posts/
  queue/
    backlog/
    ignore/
  done/
  failed/
  order.txt
scripts/
  update-venv.sh
  load-venv.sh
  get_blogger_token.py
  extract-refresh-key.py
  diagnose-oauth-config.py
  manage-posts.py
  build-and-verify.sh
  test-blogger-config.sh
src/
  config.py
  markdown_posts.py
  state.py
  scheduling.py
  notifications.py
  blogger_api.py
  posting_runtime.py
  post_management.py
  blogger_auto_poster.py
  prepare_posts.py
Dockerfile
docker-compose.yml
requirements.txt

Die Aufteilung ist bewusst pragmatisch:

  • scripts/manage-posts.py ist nur die interaktive Bedienung.
  • src/markdown_posts.py kennt Markdown, Frontmatter, Labels und HTML-Erzeugung.
  • src/blogger_api.py kapselt OAuth und Blogger-API-Aufrufe.
  • src/posting_runtime.py enthält den automatischen Posting-Zyklus.
  • src/post_management.py enthält manuelle Aktionen wie aktualisieren, offline nehmen oder veröffentlichen.
  • src/state.py verwaltet die lokale Tracking-Datei.
  • src/notifications.py kümmert sich um Pushover.
  • src/blogger_auto_poster.py ist nur noch der CLI-Einstieg für den Container und Kompatibilitäts-Exports.

Markdown-Queue

posts/queue/ enthält die aktiven Markdown-Dateien, die der Server verarbeiten darf. posts/queue/backlog/ enthält geparkte Entwürfe, die der Server ignoriert, die aber vom Management-Script bewusst ausgewählt werden können. posts/queue/ignore/ enthält Dateien, die erhalten bleiben, aber nicht automatisch gepostet werden.

Jede Markdown-Datei hat Frontmatter:

---
title: "PowerMgr"
labels:
  - Smart Home
  - Energie
  - PV
---

Die Freigabe ist absichtlich einfach und erfolgt über Ordner:

  • posts/queue/: aktiv, darf vom Server verarbeitet werden.
  • posts/queue/backlog/: geparkt, wird vom Server nicht automatisch verarbeitet, kann aber vom Management-Script ausgewählt werden.
  • posts/queue/ignore/: ignoriert oder Rohmaterial.

Nach erfolgreichem Upload wandert die Datei nach posts/done/. Fehlerhafte Dateien, die nicht gelesen werden können, wandern nach posts/failed/. Der lokale Upload-Status wird zusätzlich in posts/state.json gespeichert.

Wichtig ist die Trennung zwischen lokaler Datei und Blogger-Post: posts/done/ bedeutet nur, dass die Markdown-Datei lokal bereits verarbeitet wurde. Der Eintrag kann mit einem Blogger-Post verknüpft sein, muss es aber nicht mehr sein, wenn der Post auf Blogger gelöscht wurde oder nicht mehr auffindbar ist.

Labels

Labels werden direkt in die Markdown-Dateien geschrieben. Dadurch ist jede Datei für sich vollständig. Das Upload-Script muss nicht raten, welcher Post welche Kategorien braucht.

Die Config enthält keine Label-Regeln. Bestehende Labels können über das Management-Script aus Blogger als Referenz gelesen werden. Vor echten Blogger-Schreibzugriffen gleicht das Tool die Schreibweise der lokalen Labels mit den vorhandenen Blogger-Labels ab. Neue Labels sind erlaubt, werden aber im Log als neu ausgewiesen.

Zusätzlich haben automatisch erzeugte Dateien das Label KI generiert. Damit bleibt im Blog nachvollziehbar, welche Artikel aus diesem Dokumentationsworkflow stammen.

Upload-Zyklus

Der Auto-Poster läuft im Container. In der Config steht das Intervall:

posting:
  interval_seconds: 604800

604800 Sekunden sind eine Woche. Wenn ein Post fällig ist, nimmt das Script die nächste Datei direkt aus posts/queue, wandelt Markdown nach HTML, setzt Titel und Labels und legt den Post über die Blogger API an. Die Reihenfolge kommt aus posts/order.txt; Dateien, die dort nicht stehen, folgen alphabetisch nach Dateiname.

Dabei wird ein unsichtbarer Tracking-Kommentar in den Blogger-Post geschrieben. Dadurch kann das Tool einen vorhandenen Blogger-Post später wiederfinden und aktualisieren, statt versehentlich einen zweiten Post zu erzeugen.

Sicherheitsmodus

Initial ist der Auto-Poster auf Dry-Run gestellt:

posting:
  dry_run: true
  publish_mode: "draft"

So kann man prüfen, welcher Post als nächstes hochgeladen würde, ohne Blogger zu verändern. Für den echten Betrieb wird dry_run auf false gesetzt. publish_mode: draft ist die vorsichtige Variante, weil Blogger dann nur Entwürfe erzeugt.

Für geplante Veröffentlichung gibt es zusätzlich:

posting:
  dry_run: false
  due_mode: "weekly_schedule"
  publish_mode: "scheduled"
  schedule:
    weekday: "friday"
    time: "09:00"
    timezone: "Europe/Berlin"

Damit prüft der Container regelmäßig die Queue, startet echte Uploads aber nur am eingestellten Wochentag zur eingestellten Uhrzeit.

Blogger OAuth

Der Auto-Poster loggt sich nicht mit Benutzername und Passwort bei Blogger ein. Er nutzt die offizielle Blogger API über Google OAuth 2.0.

Die lokale Einrichtung besteht aus drei Teilen:

  • credentials.json: OAuth-Client-Datei aus Google Cloud, bleibt lokal und wird nicht committed.
  • config/config.yml: lokale Runtime-Config mit Blog-ID, Client-ID, Client-Secret und Refresh-Token.
  • config/config.example.yml: versioniertes Beispiel ohne echte Secrets.

Der wichtigste Stolperstein war der Unterschied zwischen Authorization Code und Refresh Token. Die Callback-URL aus dem Browser enthält einen temporären code=... Wert. Dieser Code gehört nicht in die Config. Er muss erst gegen einen echten Refresh Token getauscht werden.

Dafür gibt es zwei Helper:

scripts/get_blogger_token.py
scripts/extract-refresh-key.py

get_blogger_token.py ist der normale Weg, wenn der Browser auf demselben System geöffnet werden kann. extract-refresh-key.py ist für den Server-Fall gedacht: Die Google-Login-URL kann auf einem anderen Rechner geöffnet werden, die komplette Callback-URL wird danach in das Script kopiert. Das Script tauscht den Code gegen einen Refresh Token und aktualisiert die lokale Config.

Zur Prüfung gibt es:

scripts/test-blogger-config.sh --software
scripts/test-blogger-config.sh --oauth
scripts/test-blogger-config.sh --blogger-draft

Der Software-Test prüft die Modulstruktur, Python-Syntax, CLI-Einstiegspunkte und den manuellen Update-Pfad ohne Blogger-Schreibzugriff.

Der Draft-Test erzeugt einen temporären Blogger-Entwurf, prüft die API-Antwort und löscht den Entwurf danach wieder. Er lädt keinen Markdown-Artikel aus der Queue hoch. Wenn das erfolgreich ist, funktionieren Token, Scope, Blog-ID und Schreibrechte.

Lokale Python-Umgebung

Für lokale Python-Scripte gibt es ein venv-Setup:

scripts/update-venv.sh
. scripts/load-venv.sh

update-venv.sh baut .venv neu auf, installiert requirements.txt und prüft die lokalen Python-Einstiegspunkte. load-venv.sh muss mit führendem Punkt geladen werden, weil ein normales Shell-Script die aufrufende Shell nicht dauerhaft aktivieren kann.

Pushover Benachrichtigungen

Der Auto-Poster kann vor echten Blogger-Schreibzugriffen und bei Fehlern Pushover-Nachrichten senden. Dabei wird nicht direkt die Pushover-API aus dem Container angesprochen, sondern der interne Pushover-Proxy aus dem eigenen Pushover-Server-Projekt.

Die Config sieht dafür vereinfacht so aus:

notifications:
  pushover:
    enabled: true
    host: "pushover-app-server"
    port: 8090
    mode: "get"
    token: "PUSHOVER_APP_TOKEN"
    app_name: "Blogger Auto Poster"
    dedupe_prefix: "blogger-auto-poster"

Das entspricht dem vorhandenen Pushover-Proxy-Vertrag: ein HTTP-Aufruf auf /send mit Token, Titel, Nachricht und optionalem dedupe_key. Der Dedupe-Key verhindert doppelte Nachrichten bei wiederholten Tests oder Retry-Situationen.

Benachrichtigt wird unter anderem bei:

  • echtem Uploadversuch als Draft, Live-Post oder geplanter Post
  • Update eines bestehenden Blogger-Posts
  • Fehler im Posting-Zyklus
  • fehlgeschlagenem Blogger-Draft-Test
  • nicht lesbarer Markdown-Datei, die nach failed verschoben wurde

Auch Pushover wird über das Testscript geprüft:

scripts/test-blogger-config.sh --pushover

Ohne Parameter führt das Testscript den kompletten Check aus: Container vorhanden, Dry-Run, OAuth, Pushover und temporärer Blogger-Draft.

Management-Script

Für den normalen Betrieb reicht der Container. Für manuelle Arbeit an der Queue gibt es zusätzlich ein interaktives Management-Script:

scripts/manage-posts.py --config config/config.yml

Das Script listet Markdown-Dateien mit Titel und Labels. Je nach Aktion werden unterschiedliche Ordner angeboten: normale Wartungsaktionen arbeiten mit aktiven Queue-Dateien oder bereits verarbeiteten Done-Dateien, Aktion 1 zeigt zusätzlich Backlog-Dateien an, weil sie der vorgesehene Weg für Upload, Reupload und Update ist. Backlog-Dateien werden also nicht vom Server verarbeitet, können aber bewusst über die Management-Aktion ausgewählt werden.

Bei done Dateien zeigt das Script zusätzlich, ob der lokale Artikel linked oder not linked ist. linked bedeutet: In posts/state.json ist eine Blogger-Post-ID bekannt. not linked bedeutet: Die Markdown-Datei liegt zwar lokal in done, aber das Tool kennt keinen aktuellen Blogger-Post dazu.

Danach können die wichtigsten Wartungsaktionen direkt ausgeführt werden:

  1. Einen ausgewählten Queue-, Backlog- oder Done-Post mit dem konfigurierten publish_mode hochladen oder aktualisieren.
  2. Einen Blogger-Post offline nehmen, also zurück auf Draft setzen, ohne ihn zu löschen.
  3. Einen Blogger-Draft direkt veröffentlichen.
  4. Einen bestehenden Blogger-Post jetzt aktualisieren.
  5. Blogger-Status und die Verknüpfung lokale Datei -> Blogger post id anzeigen.
  6. Die aktuell auf Blogger vorhandenen Labels anzeigen.
  7. Einen Backlog-Post nur aktivieren, aber noch nicht hochladen.
  8. Einen bereits erkannten Blogger-Post löschen.

Die Aktionen zum Offline-Schalten, Veröffentlichen, Aktualisieren, Statusanzeigen und Löschen brauchen eine bestehende Blogger-Verknüpfung. Ein not linked Artikel kann dafür nicht verwendet werden, weil keine Blogger-Post-ID vorhanden ist. Für einen neuen Upload eines not linked Artikels ist Aktion 1 zuständig.

Aktion 1 ist der normale Weg für neue Uploads, Reuploads und Updates. Das Script zeigt aktive Queue-Dateien, Done-Dateien mit oder ohne Blogger-Verknüpfung und Backlog-Dateien an. Eine verknüpfte Done-Datei wird direkt als bestehender Blogger-Post aktualisiert. Eine nicht verknüpfte Done-Datei wird als neuer Blogger-Post hochgeladen und danach neu in posts/state.json verknüpft. Eine Backlog-Datei wird zuerst auf Blogger geschrieben. Wenn es bereits eine lokale Blogger-Verknüpfung für diese Quelle gibt, wird der bestehende Blogger-Post aktualisiert. Erst nach erfolgreichem Blogger-Write wird eine gleichnamige lokale Datei aus posts/done/ nach posts/done/archive/ archiviert und die Backlog-Datei nach posts/done/ verschoben. Wenn die lokal gespeicherte Blogger-ID auf Blogger nicht mehr existiert und Blogger 404 zurückgibt, erstellt Aktion 1 den Post neu und speichert die neue Blogger-ID.

Aktion 7 ist nur noch für den Sonderfall gedacht, dass ein Backlog-Artikel zwar in die aktive Queue verschoben werden soll, aber der Upload später durch den Server oder einen separaten manuellen Lauf passieren soll.

Wenn derselbe Artikel lokal in mehreren Ordnern liegt, gruppiert Aktion 1 diese Kopien über die source_id und zeigt nur die aktive Kopie an. Die Reihenfolge ist posts/queue/, dann posts/queue/backlog/, dann verknüpfte Dateien aus posts/done/. Dadurch verdeckt eine ältere Done-Kopie nicht mehr eine neuere Backlog-Bearbeitung.

Beim lokalen Aufruf übersetzt das Management-Script die Docker-Pfade aus der Config automatisch auf das Repository: /data/queue wird zu posts/queue, /data/done zu posts/done und /data/state.json zu posts/state.json. Damit kann dieselbe config/config.yml für Container und Host-Wartung verwendet werden. Wenn die Config-Pfade bewusst unverändert genutzt werden sollen, gibt es dafür --use-config-paths.

Damit muss man für typische Betriebsfälle keinen API-Aufruf von Hand bauen und keine Markdown-Datei manuell zwischen Backlog, Queue und Done kopieren. Ein gelöschter oder not linked Artikel wird über Aktion 1 aus dem Backlog neu aktiviert und hochgeladen.

Build, Start und Test

Der Server-Betrieb läuft über docker-compose:

scripts/build-and-verify.sh

Das Script baut das Image, startet den Container und führt einen sicheren Dry-Run aus.

Wenn der Container läuft, prüft das Post-Start-Testscript die Installation:

scripts/test-blogger-config.sh --all

Die Ausgabe ist als Checkliste aufgebaut: Preflight, Software-Selbsttest, Dry-Run, OAuth, Pushover und temporärer Blogger-Draft. Am Ende gibt es eine kompakte PASS/SKIP/FAIL-Zusammenfassung.

Warum das nützlich ist

Der größte Vorteil ist nicht die Automatisierung an sich. Der Vorteil ist, dass viele alte Projekte wieder sichtbar werden. Statt in alten Ordnern zu verschwinden, bekommen sie eine einheitliche Struktur, passende Labels und eine klare Entscheidung: aktiv posten, im Backlog parken oder ignorieren.

So kann aus einem gewachsenen Entwicklungsordner schrittweise ein technisches Blogarchiv entstehen.

PowerMgr: Mein selbst gebautes Energie- und Smart-Home-System

PowerMgr: Mein selbst gebautes Energie- und Smart-Home-System PowerMgr ist mein eigenes Home-Energy-Management-System. Es verbindet Photov...