Blog: Latest Entries (15):


Mega Drive und SNES Trays

Jeder der ein paar mehr Spiele für den Mega Drive oder SNES hat, hat auch eine gewissen Anzahl loser Module rumliegen.
Die Trays die ich bei Thingiverse gefunden hatte, hatten alle das Problem, dass der Boden wirklich nur eine oder max zwei Schichten dick war und entsprechend beim Ablösen auch mal einfach kaputt ging.

bbcode-image


Deswegen habe ich die etwas verbessert und stabiler gemacht:
Mega Drive
SNES

CSV und nach Datum sortieren in Libre Office

Ich hatte das Problem, dass egal was ich versucht habe den Daten einer CSV sich nicht nach der Spalte mit dem Datum sortieren lassen wollten. Ich hab versucht die Spalte als Datum zu formatieren, aber das hat nicht geholfen. Am Ende war die Lösung:

Die Datum-Daten markieren. Suchen und Ersetzen aufrufen.

Suchen nach:

^.*$


Ersetzen durch:

$


und noch auswählen, dass nur im markierten Bereich gesucht werden soll und natürlich dass das ein RegEx-Ausdruck ist.

Die Lösung habe ich hier https://www.libreoffice-forum.de/viewtopic.php?t=9488 gefunden.

'bash' Befehl in Powershell fixen

Ich hatte das Problem, dass der Befehl 'bash' nicht mehr mir die Bash meines WSL Ubuntu geöffnet hat sondern irgendwas machte und dann wieder in die Powershell zurück wechselte ohne was anzuzeigen. Das Problem kam wohl daher, dass ich Docker mit WSL vor Ubuntu installiert hatte. Also kein Hyper-V und kein Ubuntu. Daher war der 'bash' Befehl auf Docker gemappt und nicht auf das Ubuntu.

Prüfen:

wslconfig /L


Ändern:

wslconfig /setdefault Ubuntu-20.04

Gameboy Module aufbewahren

Nachdem ich mit den Mega Drive und SNES Sachen von Thingiverse nicht wirklich zufrieden war, habe ich jetzt die Lösung für den Gameboy komplett selbst entworfen. Mit dem billigen PLA von eBay gedruckt.. mich über das PLA geärgert.. das biegt sich manchmal an der linken vorderen Ecke nach oben.. egal wo diese Ecke sich auf dem Bett befindet.

bbcode-image


Hier der Tinkercad-Link.

bbcode-image

EDC-Wholesale Trackingcode-Mails parsen

Man kann einen Update-Endpoint für Bestellungen definieren, der angesprochen, wenn sich der Status einer Bestellung bei EDC-Wholesale ändert. Problem ist, dass das nicht immer funktioniert und Hilfe auch nicht immer kommt. Aber man hat Mail die man parsen kann. Die wichtigsten Regex dafür sind:

Betreff:

/Auslieferung Ihrer Bestellung/


Body-Trackingcode:

/>(\d+)<\/b>/


Body-Ordernumber:

/Kontrollnummer:<\/b>\s*(\d+)<br/


Damit kann man alle Daten bekommen und seine Bestellungen updaten. Mit einer Shopware 5 Lösung kann ich gerne auf Anfrage helfen.

Ports und Adapter - Meine Definition und Erklärung

Ich hatte eine sehr genaue und von Java geprägte Vorstellung von Ports und Adaptern. Im Tomcat z.B. der HTTP-Port und dann als Adapter HTTP-NIO als Implementierung des Ports. Dann wurde diskutiert und irgendwie hatten alle andere Ansichten was ein Port und ein Adapter sind. Nachdem dann Ports da waren, aber keine Adapter mehr und Ports irgendwie nur noch deren wegen da waren, haben ich mich diesen Sonntag mal hingesetzt und angefangen im Netz zu lesen.

Erst landete ich bei eine Artikel über Ports und Adapter mit Symfony und ich fühlte mich verstanden. Dann kam der die Interpretation nutze und sogar das Repository als Adapter und sein Interface als Port sieht (was an sich ja genau richtig ist). Also mein Verständnis entspricht dem auf Baeldung.com beschriebenen Grundgedanken einer Logic die zwischen nicht kompatiblen Interfaces vermitteln. Zumeist ist eines der Interfaces, das der eigenen Anwendung und das andere das einer 3rd Party Lib.

Also wäre an sich auch JPA ein Port. Es beschreibt ein allgemein gültiges Interface zur Persitierung und die verschiedenen Frameworks wie Hibernate oder EclipseLink liefern Adapter die JPA auf die nativen Interfaces adaptiert.

Dadurch definieren sich schon mal ein paar Dinge:
- es kann keinen Port ohne Adapter geben
- Ein Adapter ist nötig, wenn das Interface nicht mit der eigenen Anwendung kompatible ist

Im Grunde sind wir hier wieder beim klassischen Factory-Patten. Ein allgemeines Interface, viele Implementierung und eine Instanz die entscheidet welche Implementierung gerade die passende ist. Nebenbei in Unit-Tests sehr praktisch.

Wann brauche ich keinen Port:
- Wenn eine Lib schon ein allgemeines Interface bereit stellt
- z.B. was bei den meisten Email-Libs so ist... weil die Änderung der Implementierung oft nur Konfiguration ist
- etwas allgemeines noch mal zu Kapsel macht wenig Sinn
- Ein Adapter für nur eine mögliche Implementierung macht genau so wenig Sinn

Ein sehr fachliches Beispiel wäre das Pushen einer Bestellung an verschiedene Drop-Shipper. Jeder hat ein anderes WWS, ERP oder Shop-System. Man definiert für die Clients ein einheitliches Interfac, was mit den eigenen Klassen (bzw. deren Interfaces) arbeitet. Für jedes System wird ein eigener Client geschrieben und Abhängig vom Drop-Shipper und seinen Systemdaten wird eine Factory die passende Implementierung wählen und konfigurieren.

Also... Ports und Adapter ist kein Konzept, dass man groß erzwingen muss, es ergibt sich zwangsmäßig und von alleine (wenn man nur minimal strukturiert entwickelt).


PS:
Wenn man mehr als eine Domain hat, definiert natürlich nur eine Domain das Interface und stellt die Verwendung den anderen Domainen per UseCase zur Verfügung.

Von der Ring Doorbell zum Fitbit Charge 4

Wir haben eine Ring Doorbell. Damit man auch im Urlaub weiß was an der Haustür so los ist.

bbcode-image


Das Problem ist nur die niedrige Lautstärke und die sehr generische Meldung über Alexa. Nach der Idee ein Outdoor-Alexa zu basteln oder einfach ein Ring Chime zu kaufen, kam die Idee doch eine haptische Meldung über die Fitbit Charge 4 zu versuchen. Mehr Smartes Spielzeug und so.. was soll schon schief gehen. Abert wie bekommt man eine Benachrichtigung auf die Fitbit? DAs geht über Alexa und die
generischen Android Benachrichtigungen. Man erstellt sich dazu eine einfache Routine.

* "Wenn folgendes passiert"
* "Smarthome" + "Haustür" (oder wie die Ring eben genannt wurde)
* dann das Klingeln auswählen
* Als Aktion und Nachrichten den Punkt "Benachrichtigung" auswählen
* hier etwas wie "Ring!Ring!" eintragen
* alles Speichern

Wenn nun die Klingelt gedrückt wird kommt auf dem Smartphone eine Benachrichtigung an und diese landet auch auf dem Fitbit. Wenn man nun das über mehrere Smartphones laufen lässt mit Profilen und eines nicht will: Ausloggen und wieder einloggen kann das Problem lösen.

Nun bleibt am Ende nur das Problem mit der Reichweite von Bluetooth.. aber das werden wir auch noch lösen.

PHPStorm mit Xdebug

Auf Wunsch hier nochmal eine kleine Anleitung wie man Xdebug in einem Docker-Container zusammen mit PHPStorm verwendet. Ich hatte ja schon eine Anleitung für VSCode geschrieben und dort am Ende angemerkt, dass es mit PHPStorm sehr viel einfacher geht. Vorhin nochmal getestet und es geht sehr viel einfacher.

Aber von Anfang an. Wir müssen erstmal das Docker-Image um Xdebug erweitern:


RUN pecl install xdebug-2.8.0 && docker-php-ext-enable xdebug
RUN echo 'zend_extension="/usr/local/lib/php/extensions/no-debug-non-zts-20151012/xdebug.so"' >> /usr/local/etc/php/php.ini
RUN echo 'xdebug.remote_port=9000' >> /usr/local/etc/php/php.ini
RUN echo 'xdebug.remote_enable=1' >> /usr/local/etc/php/php.ini
RUN echo 'xdebug.remote_host=host.docker.internal' >> /usr/local/etc/php/php.ini


Dann installieren wir uns "Xdebug Helper" für den Chrome oder eben die Kombination aus Addon und Browser, die man gerne hätte.

bbcode-image


Dann den Docker-Container starten. Die Seite im Chrome aufrufen und dort das Addon aktivieren. Einen Breakpoint in PHPStorm setzen und PHPStorm auf Debug Eingänge horchen lassen.

bbcode-image


F5 im Webbrowser drücken und dann das Mapping bestätigen.

bbcode-image


Das wars. Super einfach und schnell (abgesehen vom Docker-Container bauen) eingerichtet.

bbcode-image

DDD-Cluster.. ein Diagramm

Ich nenne diese Struktur DDD-Cluster, da es ein Cluster aus mehreren Domains ist, die auch unter einander kommunizieren können und auch die Hexagonale-Architektur abbilden.

bbcode-image


Jeder der schon mal in Java eine EJB3-Anwendung mit mehreren Modules gebaut hat, sollte das darin wieder erkennen können und weiß sicher das so ein Diagramm zwar schön sauber aussieht, aber die Realität schnell ganz anders ist. Abhängigkeiten wachsen schnell und schnell gibt es Module die fast alle anderen Module benötigen und schnell zyklische Abhängigkeiten entstehen. So eine Architektur entsteht, wenn man sauber und bewusst arbeitet. Die Anwendung wird nicht sauber und strukturiert, weil es die Theorie so einer Architektur gibt.

Also nichts neues aber mal nett anzugucken. Dann denkt man an die Realität und weiß wieder warum es Microservices gibt.

Composer: Eigene Libs mit Gitlab

Man kennt Systeme wie Satis oder Toran die sich aus einem Git bei Änderungen den aktuellen Stand holen und ihn in Versionen für die Libs umwandeln. Man darf nicht vergessen die System zu triggern, um immer die aktuellen Version zu haben. Sonst ändert man was und wundert sich, dass sich nichts ändert.

Mit Gitlab kann man alles in einem haben und das in sehr einfach. Auto DevOps ist aber diesmal nicht die Lösung. Aber man braucht nur ca. 1 Minute um alles einzurichten.

bbcode-image


1) Package Repository aktivieren (wenn noch nicht so)
2) Pipelines aktivieren (unwahrscheinlich dass es noch nicht ist)
3) auf der Startseite des Projekt "Setup CI" wählen
4) Bei den Templates "composer" auswählen und mergen
5) .. fertig

bbcode-image


Schon findet man beim nächsten Push eines Branches oder Tags in der Package-Registry einen Eintrag für einem Composer-Package.

bbcode-image

Commit-Messages: Was im Branch geschrieben wird, bleibt im Branch

Wie sollen Commit-Messages aussehen? Es gibt viele gute und durchdachte Konzepte dazu.

* Einfache mit wenig Formalitäten
* Sehr umfassende, die zur automatischen Generierung von Changelogs taugen

Aber man sollte sich auch klar machen, dass diese Commit-Messages nur bei Merge Commits zum tragen kommen. Wenn man in einem Branch ist commitet man häufig (mindestens einmal am Tag) und oft auch WIP Stände. Vieles was man commited ist ungetestet und enthält noch Fehler. Am Ende macht man alles noch mal hübsch und schreibt die README.
Also hier braucht es weder "feat" noch "fix" Prefixes. Was ist insgesamt ist, sagt ja schon der Branch. Wie es innerhalb des Branches aussieht interessiert nur 1-2 Entwickler. Die Commit-Message des Merges ist interessant und da braucht man an sich keine Message aus der man ein Changelog-Eintrag erzeugen kann sondern direkt einen Changelog-Eintrag. Also macht es sich an sich mehr Sinn über das Changelog, Versionierung und Change-Dokumentierung Gedanken zu machen. Ein Template für Merge-Commits wird da schon von alleine mit abfallen.

"clean up code" und "fixes while testing" sind im Branch also voll OK.


Govee TV LED vs. Ambilight

Philips TVs mit Ambilight sind ja echt schön (auch abgesehen von der Fernbedienung) aber auch entsprechend teuer. Grundig hat TVs mit eingebauten Fire TV aber leider ohne Ambilight. Nach etwas suchen und der Entscheidung nicht mit einer Webcam und einem Raspberry Pi selbst was zu basteln habe ich mich ein Set von Govee entschieden.

Die Installation geht echt einfach, auch wenn man vielleicht die LED-Strips später noch mal kleben muss, weil die unter Spannung doch mal abgehen. Die Plastikhalterungen, die für so einen Fall beiliegen, waren leider zu breit für unseren TV. Das USB-Kabel könnte länger sein, aber eine einfach USB-A Verlängerung (30cm) sollte das Problem lösen. Die Kamera hält erstaunlich gut.

bbcode-image
ganz viel 3M-Klebezeugs


bbcode-image
Aufkleber zur einfachen Kalibrierung


Die Installation geht mit einer Mischung aus Bluetooth und WLAN sehr einfach. Wichtig ist wirklich den Vorgaben zu folgen. Licht an und TV aus. Wir haben Ikea Tradfri LED Leuchten und die sorgen schnell dafür, dass alles was die Kamera durch die Spiegelung im TV sieht blau ist. Mit Licht aus sind die Ergebnisse dann wieder stimmig. Aber für 60 Euro und eine externe Lösung (die keinen HMDI Input benötigt) funktioniert es ziemlich gut.

bbcode-image
Mit Star Wars Episode 3


Die Govee Wasserdetektoren sehen auch lustig aus, sind aber wohl in Deutschland nicht zu bekommen.

Was ist 31.1. + ein Monat?

Was ist der 31.1. + ein Monat? Den 31.2. gibt es nicht also ist es der 27.2./28.2. oder ein Tag im März?
Von der reinen menschlichen Logik wäre der Xte Tag des Monats der selbe oder der nächstgelegenste mögliche Tag. Aber nie der Tag des nächsten Monats. Wie beim ISO-Kalenderjahr geht man vom Gefühl nicht davon aus dass das neue (Kalender-)Jahr im alten (gefühlten) Jahr anfängt.


/**
* @param DateTime $date
* @param int $months
*
* @return DateTime
* @throws Exception
*/
function addMonths(DateTime $date, $months = 0) {
$firstDayDate = clone $date;
$dayOfMonth = $firstDayDate->format('d');
$firstInterval = new DateInterval('P' . ($dayOfMonth - 1) .'D');
$firstDayDate->sub($firstInterval);
$firstDayDate->add(new DateInterval('P' . $months . 'M'));
$maxDay = $firstDayDate->format('t');
if($dayOfMonth > $maxDay) {
$dayOfMonth = $maxDay;
}
$restoreIntervall = new DateInterval('P' . ($dayOfMonth - 1) . 'D');
$firstDayDate->add($restoreIntervall);
return $firstDayDate;
}


Damit wäre der 31.1. + 3 Monate der 30.4. weil immer im Context eines bestimmten Monats gerechnet wird und dieser Context nicht verlassen werden darf.


Older posts:

Möchtest Du AdSense-Werbung erlauben und mir damit helfen die laufenden Kosten des Blogs tragen zu können?