Schlagwort-Archive: Arduino

Tür öffnen mit Siri, OTP und FHEM (fInal?)

Das ist (vielleicht) mein letztes Update zum Thema Tür öffnen.

Zuerst mal eine gute Nachricht: Es gab noch keinen Versuch, sich hier widerrechtlich Zugang zu verschaffen. Das liegt aber voraussichtlich daran, dass diese Seite hier niemandem auffällt, der ernste Absichten hat, bei mir einzubrechen. Und wenn doch: Irgendwie fände ich es geil, wenn jemand sich die Mühe macht, um alle beteiligten Systeme zu hacken, um dann doch den Türöffner auszulösen, nur um dann zu sehen, dass hier nichts zu holen ist. Es wäre nur nett, wenn der- oder diejenige mir danach mitteilt, wo die Fehler in meinem Konzept waren.

Wie dem auch sei: Ich habe noch ein paar Optimierungen vorgenommen, die ich euch nicht vorenthalten möchte.

Zunächst einmal habe ich mir den „Schaltplan“ vom GIRA-Steuergerät Audio 128700 besorgt. Naja, nicht wirklich. Ich habe einfach nur endlich gecheckt, was die Symbole auf dem Gerät selber bedeuten.

Das bedeutet: Wenn man an die Terminals 7 und 8 einen Schaltkontakt anlegt, dann wird der Türöffnerkontakt ausgelöst, wenn der Kontakt geschlossen wird.

Also kann ich damit den ganzen Servo-Kram weglassen! Ich brauche also nur ein Relais-Modul am Wemos D1 und kann damit dann den Türöffner auslösen.

Also weg mit dem Servo, her mit einem Wemos D1 Relais Shield (für ’n paar günstige Taler erhältlich bei AZ-Delivery) und kurz den Sketch geändert: Dann sieht das ganze im Schaltschrank jetzt so aus:

Wemos D1 Relais Shield

Ausgang vom Relais mit Terminal 7 und 8 verbunden

Der Wemos-Sketch ist nun so geändert:

#include <Arduino.h> 
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
 
// Update these with values suitable for your network.
 
const char* ssid = "ssid";
const char* password = "wlanpw";
const char* mqtt_server = "mqtt.server.ip"; // MQTT IP oder DNS-Name
const char* servo_topic = "/SmartHome/Keller/Door/servo/cmnd"; // Topic braucht ihr später noch in FHEM
const char* status_topic = "/SmartHome/Keller/Door/servo/stat"; // Topic braucht ihr später noch in FHEM
  
WiFiClient espClient;
PubSubClient mqttClient(espClient);
// long lastMsg = 0;
// char msg[50];
int interval = 0;
const int relayPin = D1;
int relayState = LOW;

void setup_wifi() {
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
 
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}
 
void callback(char* topic, byte* payload, unsigned int length) {
  String payloadstring;
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (unsigned int i = 0; i < length; i++) {
    // Serial.print((char)payload[i]);
    payloadstring+=((char)payload[i]);  
  }
   
  if (strcmp(topic, servo_topic) == 0)  
    interval = payloadstring.toInt();
    Serial.println(payloadstring);
    if (interval > 0) {
      digitalWrite(relayPin, HIGH); // turn on relay with voltage HIGH
      mqttClient.publish(status_topic, "opened");
      delay(interval);
      digitalWrite(relayPin, LOW);  // turn off relay with voltage LOW
      mqttClient.publish(status_topic, "closed");
    } else {
      mqttClient.publish(status_topic, "init");
    }
 }
 
void reconnect() {
  // Loop until we're reconnected
  while (!mqttClient.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (mqttClient.connect("ESP8266Client")) {
      Serial.println("connected");
      mqttClient.publish(status_topic,"connected");
      mqttClient.subscribe(servo_topic);
    } else {
      Serial.print("failed, rc=");
      Serial.print(mqttClient.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup() {
  Serial.begin(115200);
  pinMode(relayPin, OUTPUT);
  // myservo.attach(D0);
  // myservo.write(interval);
  setup_wifi();
  mqttClient.setServer(mqtt_server, 1883);
  mqttClient.setCallback(callback);
}
 
void loop() {
  if (!mqttClient.connected()) {
    reconnect();
  }
  mqttClient.loop();
}

Aber das war noch nicht alles.

Auch auf der Client-Device Seite hat sich bei mir etwas getan: Die Family besitzt jetzt Apple-Watches. Damit kann (könnte) man den Kurzbefehl auch auf der Watch ausführen. Also kann (könnte) man einfach „Tür öffnen“ in die Watch sprechen (vorausgesetzt, man ist in der Nähe des heimischen WLAN) und die Tür geht auf. Das funktioniert aber aufgrund der Siri-Architektur (jemand hat mir mal gesagt, dass jedesmal, wenn man „Hey Siri“ sagt, erstmal ein Microservice (Docker-Container) bei Apple hochgefahren werden muss, um die Anfrage zu bearbeiten) nur bedingt schnell… Nix ist peinlicher, als dass jemand vor der Haustür steht und mehrfach „Tür öffnen“ in sein Handgelenk spricht und nix passiert. Manchmal klappt das aber.

Andererseits können aber die aktuellen iPhones auch NFC-Tags in eine Kurzbefehl-Automatisierung einbauen. Und da wird es schon wieder spannend:

Warum also nicht irgendwo „hinter“ (also innen an) der Haustür einen NFC-Tag anbringen und zwar so, dass ein aktuelles iPhone diesen Tag erkennt und dann den Kurzbefehl „Tür öffnen“ ausführt.

Und jetzt könnte die Frage gestellt werden: Warum das iPhone an die Tür halten (inkl. Face-/Touch-ID Entsperrung), um die Tür zu öffnen, wenn es der Schlüssel genauso tut?

Die Antwort kann man nicht rational beantworten. Aber es ist einfach cool, wenn man’s kann.

Tür öffnen mit OTP und Siri-Shortcuts

Kurzer Disclaimer vorweg: Alles was ihr jetzt lest und ggf. nachmacht, macht ihr auf eigene Gefahr. Die hier vorgestellte Lösung ist dazu geeignet, dass ihr den Inhalt eueres Hauses verlieren könnt. Wenn ihr irgendetwas davon nachmachen wollt, solltet ihr sicher sein, dass das was ihr hier lest, auch komplett verstanden und von euch nachvollzogen werden kann. Ich hab‘ euch jedenfalls gewarnt!

Was wird benötigt, um das ganze zu verstehen?

  • Fundierte FHEM-Kenntnisse
  • Eine gegenüber dem Internet abgeschottete FHEMWEB-Instanz
  • FHEM kann aus dem Internet über DynDNS erreicht werden
  • Ein iOS Gerät mit der Kurzbefehle-App und Kenntnisse, wie man einen Siri-Shortcut erstellt
  • Programmierkenntnisse in der Arduino-IDE (oder vergleichbaren Lösungen)
  • Einen MQTT-Broker und Kenntnisse, wie das MQTT Protokoll funktioniert
  • Einen WeMos D1 Mini und ein wenig Verständnis, wie der funktioniert
  • Ein kleines SG90 Servo (zumindest in meinem speziellen Fall, aber dazu später)
  • Ein wenig „vorhandene“ Hardware z.B. Breadbord, Jumperwires usw. was man als Maker so eben braucht

So und jetzt geht’s los.

Seit einigen Jahren setze ich FHEM zur Hausautomatisierung ein. Seit den ersten Tagen habe ich eine Möglichkeit gesucht, über FHEM meine Haustür öffnen zu können. Und das möglichst charmant und natürlich auch sicher. Die Haustür hat einen elektrischen Türöffner, der über ein GIRA Steuergerät Audio 1287 00 und entsprechende Türsprechstellen bzw. Wohnungsstationen ausgelöst werden kann.

Leider gab es hier immer zwei kleinere Hürden zu überwinden:

Das Steuergerät von GIRA wird über ein Bus-System gesteuert, zu dem es – zumindest für mich – keine Protokollbeschreibungen gibt. Außerdem kann ich an den Wohnungsstationen nur dann die „Tür öffnen-Taste“ bedienen, wenn vorher jemand an der Türstation geklingelt hat… Irgendwie in diese vorhandenen Geräte einzugreifen und über Relais, Optokoppler oder sonstwas die Tür zu öffnen und dabei das komplette „System“ zu gefährden, kam also nicht in Frage.

Die zweite Hürde war, das ganze irgendwie gegen Missbrauch abzusichern. Natürlich kann man in FHEM Befehle ja über einen URL-Aufruf per http im Browser ausführen. Aber FHEM ungesichert aus dem Internet erreichbar zu machen? No way! Die Instanz mit einem Benutzer und einem komplexen Passwort abzusichern? Schon besser. HTTPS verwenden über einen Reverse-Proxy und let’s encrypt Zertifikaten? Wir kommen dem Ziel schon näher.

Doch zunächst zur ersten Hürde zurück. Zum Glück gibt’s von dem Steuergerät eine Bedienungsanleitung in der folgendes steht:

Die Taste „Türöffnerprogr.“ hat zwei Funktionen:

  1. Türöffner-Programmiermodus einschalten:
    Wird die Taste „Türöffnerprogr.“ für 3 s gedrückt, während sich das System im Programmiermodus befindet, wird der Türöffner-Programmiermodus aktiviert … blablabla
  2. Betätigung des angeschlossenen Türöffners.
    Durch kurzes Drücken der Taste „Türöffnerprogr.“ wird der Türöffner für die eingestellte Zeit (Türöffnerzeit) aktiviert…

Aha! Der zweite Punkt lässt sich also mit ein wenig Hardware lösen: Ein kleines Servo gesteuert von einem WeMos D1 mini sollte doch diese kleine Taste betätigen können. Und der WeMos wäre ja auch nicht der erste, der sich im Schaltschrank befindet. Ein wenig Recherche im Netz und der Code für die Servosteuerung über MQTT war fertig:

/*
Wifi, MQTT und Servo
*/

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

#include <Servo.h> 
Servo myservo; 

// Update these with values suitable for your network.

const char* ssid = "SSID";
const char* password = "WLANPASSWORT";
const char* mqtt_server = "MQTTBROKER"; // MQTT IP oder DNS-Name
const char* servo_topic = "/servo/cmd"; // Topic braucht ihr später noch in FHEM
 
WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;

void setup() {
  Serial.begin(115200);
  myservo.attach(2);
  myservo.write(value);
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}

void setup_wifi() {

  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void callback(char* topic, byte* payload, unsigned int length) {
   String string;

  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
   // Serial.print((char)payload[i]);
     string+=((char)payload[i]);  
  }
  
  Serial.print(string);

  if (strcmp(topic, servo_topic) == 0)  
    Serial.print(" ");
    int resultado = string.toInt();   
    int pos = resultado;
    Serial.println(pos);
    myservo.write(pos);
    delay(300);
    myservo.write(0);
 }

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("ESP8266Client")) {
      Serial.println("connected");
      client.subscribe(servo_topic);
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}
void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  delay(100);
}

In den markierten Zeilen noch die eigenen Daten eintragen SSID, WLAN-Passwort, MQTT-Broker und Topic und ab damit auf den WeMos. Kleine Anmerkung: Der Code ist quick and dirty zusammengeschustert. Hier fehlt noch z.B. WifiManager mit eigenen Parametern verwenden, Servo-Status publishen, Telemetrie-Daten des WeMos per MQTT publishen, LWT festlegen, Serial-Output mit debug-flag ein- und ausschaltbar machen usw. Ihr könnt gerne mithelfen 😉

Eine Sache im Code ist ganz wichtig: Bevor irgendeine Ausgabe auf der seriellen Schnittstelle erfolgt, muss das Servo initialisiert werden und auf seine 0-Stellung gesetzt werden. Wenn im Setup schon serial.print Befehle drin sind, dann spinnt das Servo. Wenn es dann in seiner Position ist, kann es sich auch mal weiter drehen, als notwendig, und dann ggf. doch die Taste evtl. zu lange drücken oder sich in die falsche Richtung drehen und mit dem Hebel am Steuergerät hängen bleiben. Was dann mit dem WeMos passiert? K.P.!

Für die Schaltung mache ich kein Fritzing auf. Mein Servo hat ein rotes, ein braunes und ein orangenes Kabel. Rot kommt am WeMos an 3,3V (oder 5V), braun an GND und orange an D4 (daher im code oben myservo.attach(2) – PIN2 ist D4 auf dem WeMos).

WeMos auf Breadboard im Multimedia-Feld im Schaltschrank

Das Servo wird nun an geeigneter Position auf dem Steuergerät befestigt:

ob es tatsächlich so schlau war, die grüne, dauerleuchtende Status LED des Steuergerätes mit dem Servo zu überkleben, werden wir in ein paar Wochen sehen…

Weiter geht es mit der zweiten Hürde: Absicherung der Lösung und Integration in FHEM.

Halten wir folgendes fest: FHEM ist aus dem Internet über https mit einem gültigen Zertifikat und einer definierten URL über DynDNS erreichbar und mit Benutzer und Passwort abgesichert, am besten noch mit einer eigenen FHEMWEB-Instanz. Stimmt’s? Wenn nicht: Sorry, aber das sind Basics, die müsst ihr euch anderweitig erarbeiten. Alles andere wäre jetzt grob fahrlässig und dann bitte die folgenden Schritte nicht nachmachen. Schreibt mir ggf. eine Mail und ich schicke euch Links dazu, die ich für meine FHEM-Installation genutzt habe, um diese Anforderungen zu erfüllen.

Die Überschrift sagt ja was von OTP und Siri-Shortcuts. Also kümmern wir uns zunächst mal um OTP: Ein „Einmalkennwort“.

https://de.wikipedia.org/wiki/Einmalkennwort

In FHEM gibt es ein GoogleAuth-Modul. Dieses kann man wie folgt anlegen:

defmod GoogleAuth GoogleAuth
attr GoogleAuth DbLogExclude .*
attr GoogleAuth ga_labelName FHEM

Weitere Infos dazu hier bei Matthias Kleine auf YouTube

Damit hat man dann eine zusätzlich Funktion in FHEM, um über eine Authenticator-App auf dem Smartphone ein OTP zu generieren und dieses in FHEM auf Gültigkeit zu prüfen.

Um jetzt FHEM „von Außen“ das OTP zu übergeben, legen wir mal ein Dummy-Device an:

defmod gAuthTest dummy
attr gAuthTest DbLogExclude .*
attr gAuthTest readingList AuthCode
attr gAuthTest setList AuthCode
attr gAuthTest stateFormat AuthCode

Damit geht ja schon mal folgendes:

https://meine.fhem.instanz/fhem?cmd=set%20gAuthTest%20AuthCode%20OTP_aus_der_App&XHR=1

… äh, nein! Stichwort csrfToken

Ich empfehle dazu folgenden Link https://wiki.fhem.de/wiki/CsrfToken-HowTo

Also alles etwas komplizierter, aber ihr seid ja Experten (sonst wäret ihr gar nicht hier).

Also, nachdem wir es nun erfolgreich geschafft haben über eine URL das Reading „AuthCode“ im Device „gAuthTest“ zu setzen, legen wir uns noch ein Notify an, welches überprüft, ob das ein gültiges OTP war:

defmod n_ValidateGAuth notify gAuthTest:AuthCode:.* {\
if (gAuth("GoogleAuth", ReadingsVal("gAuthTest", "AuthCode", "")) == 1) {\
			fhem("set DoorServo Value 25");;\
		}\
}
attr n_ValidateGAuth DbLogExclude .*
attr n_ValidateGAuth room 97_Logic

Hier habe ich jetzt etwas vorgegriffen. Der set-Befehl im Notify funktioniert natürlich noch nicht, weil das Device DoorServo nicht existiert. Also holen wir das schnell nach;

defmod DoorServo MQTT_DEVICE
attr DoorServo DbLogExclude .*
attr DoorServo IODev mqtt
attr DoorServo publishSet_Value /servo/cmnd
attr DoorServo room MQTT

Hier könntest Du jetzt einen Test machen, um alles in FHEM und auf dem WeMos programmierte zu prüfen, in dem Du einfach mal z.B. im Browser versuchst das Reading AuthCode im Device AuthTest zu setzen. Wenn Du das OTP korrekt in der URL eingegeben hast, dann sollte sich das Servo nun kurz um 25° bewegen und dann wieder auf die 0-Stellung zurückfallen. Wenn das OTP nicht passt, dann passiert einfach gar nix.(Und hier erwarte ich eine Menge Feedback, weil das so einfach nicht ist. Stichworte: URL mit BasicAuth aufrufen, URL codieren, csrf-Token korrekt angeben usw. Aber: Das muss verstanden werden und funktionieren, sonst geht’s hier nicht weiter. Fragen? Gerne per Mail.)

Also weiter gemäß der Überschrift im Beitrag. OTP ist also geklärt nun kommt Siri dran.

Ich meine, seit iOS 11 gibt es die Siri-Shortcuts und mittlerweile auch die „Kurzbefehle-App“ auf iPhones und iPads. Wer sich etwas mit den Apple Betriebssystemen auskennt, weiß vielleicht, dass es in Betriebssystemen von Apple immer eine Möglichkeit der IAC=“Inter Application Communication“ gegeben hat. Auf dem Mac gab es schon in den 90er’n AppleScript. Ich behaupte, dass viele Betriebe, die sich in den 90er’n hin zu Multimedia-Betrieben entwickelt haben, ohne AppleScript nicht überlebt hätten. Über AppleScript konnten Programme untereinander und mit dem Betriebssystem interagieren. Und das noch über eine „lesbare“ Programmiersprache. Die Weiterentwicklung war dann in Mac OS X der „Automator“ und als letztendliche Konsequenz kam dann diese Funktionalität auch mit den Siri-Shortcuts bzw. der Kurzbefehle-App auf Apple’s mobiles Betriebssystem iOS. (Sorry für den Exkurs, aber das war, ist und bleibt ein Grund für mich, Apple-Systeme zu nutzen. Ich stehe einfach auf IAC 😉 )

Und all das hilft uns jetzt, das „Problem“ zu lösen!

Wie wäre es, wenn man folgendes tun könnte:

  • „Hey Siri, Tür öffnen“
  • Siri antwortet mit „Gib den Zugangscode ein“
  • „123456“ zu Siri zu sprechen und die Tür geht auf

Und genau das machen wir jetzt abschließend zu dem Beitrag.

Anmerkung: Es ist leider nicht ganz so einfach, den Siri-Shortcut in Form von Text zu exportieren. Aufgrund der verwendeten Zugangsdaten zu FHEM werde ich diesen Kurzbefehl hier nicht zum Download anbieten. Daher werde ich Text und Bild verwenden, um euch den Kurzbefehl zu erklären.

Zunächst aktivieren wir in den Einstellungen des iOS Devices für die Kurzbefehle-App die Option „Nicht vertrauensw. erlauben“ (ob das wirklich notwendig ist, muss ich noch recherchieren, aber wir machen das jetzt einfach mal).

Wir starten mit dem Aufruf der Kurzbefehle-App, gehen auf „Meine Kurzbefehle“ und wählen „Kurzbefehl erstellen“ aus. Den Kurzbefehlnamen nennen wir „Tür öffnen“. Damit geht schon mal „Hey Siri, Tür öffnen“. Als erste Aktion fügen wir „Nach Eingabe Fragen“ ein und definieren die Frage „Gib den Zugangscode ein“. Eingabetyp ist „Text“ (weil das OTP auch mit einer Null beginnen kann).

Die Nächste Aktion ist „Variable konfigurieren“. Diese nennen wir „sOTP“ und setzen sie auf „Eingabe breitgestellt“ fest.

Die nächste Aktion ist „Text“. Hier geben wir die externe FHEM-URL ein und (leider) zwar mit der Angabe von Username und Passwort (Wenn jemand da eine andere Möglichkeit kennt: Her damit!) Also lautet die URL dann beispielsweise so:

https://username:passwort@meine.fhem.instanz

Als nächstes brauchen wir eine neue Aktion „zu Variable hinzufügen“ Und zwar fügen wir den Text zu sBaseURL hinzu.

Dann brauchen wir noch eine „Text“-Aktion. Diese enthält den FHEM-Befehl und wird ergänzt mit der Variable sOTP.

Dann brauchen wir eine URL Codieren Aktion (wie immer am besten die Suche verwenden, damit man diese Aktionen schnell finden kann). Mit dieser Aktion codieren wir den Text, damit Leerzeichen etc. entsprechend ersetzt werden.

Die dann folgende Aktion ist „Variable konfigurieren“. Hier legen wir die Variable sCMD auf den Text der codierten URL fest. Die Schritte sehen dann so aus:

So, jetzt kommt ein „tricky-part“. FHEM bzw. FHEMWEB hat seit einiger Zeut ja einen Schutzmechanismus gegen Cross-Site-Scripting-Attacks eingebaut. Das ganze wird über das csrf-Token geregelt. Und genau das holen wir uns jetzt mit den nächsten 3 Aktionen.

Die erste davon ist „Header von URL abrufen“. Hier bauen wir uns die URL wie folgt zusammen: sBaseURL/fhem?XHR=1

Die nächste Aktion ist „Wörterbuchwert abrufen“. Damit holen wir uns letztendlich aus einem named-array einen bestimmten Wert (Was für eine blöde Übersetzung). Und zwar den Wert für X-FHEM-csrfToken in Header von URL abrufen.

Die dritte Aktion, die wir jetzt brauchen ist wieder eine „Variable konfigurieren“ und zwar sCSRF auf Wörterbuchwert festlegen. Das sieht dann im Detail so aus:

wer findet den Schreibfehler?

Und zu guter Letzt rufen wir eine Aktion „Inhalte von URL abrufen auf“ und bauen darin die URL mit den einzelnen Variablen zusammen:

CSRF <> CSFR 😉

Fertig? Leider noch nicht so ganz. Beim Testen ist mir ein Eintrag im FHEM-Log aufgefallen, der wohl kein großes Problem verursacht, aber Einträge in Logfiles, die sich nicht so einfach erklären lassen, sind per se verdächtig. Es handelte sich um z.B. diese Zeile im log:

2020.05.22 20:46:50 3: WEB_192.168.xxx.xxx_12345: unsupported HTTP method HEAD, rejecting it.

Das konnte ich durch Setzen eines Attributes in der FHEMWEB-Instanz eliminieren.

attr WEB allowedHttpMethods GET|POST|HEAD

Fertig? Ja!

Making of LiquidClock Part 2

Hier kommt nun der zweite Teil des Making Of LiquidClock. Besonders viel ist nicht mehr passiert, außer dass ich dank DHL etwas länger auf die Frontfolie warten musste.

Ich hatte früher auf meinem R4 ein orangenes Tape auf dem Stand:

„Nicht werfen, vor Nässe schützen!“

Vielleicht sollte man das bei DHL wieder einführen, damit die sorgsamer mit meinem Eigentum umgehen.

Wie versprochen, hier ein paar Fotos und auch ein Video der fertigen LiquidClock.

Hier kann man noch einmal schön die weggeklappte PE-Platte sehen.
Hier kann man noch einmal schön die weggeklappte PE-Platte sehen

Hier die Uhr im Nachtmodus
Hier die Uhr im Nachtmodus

Girlie style: Die Stunden sind lila, die Minuten orange und die Sekunden gelb.
Girlie style: Die Stunden sind lila, die Minuten orange und die Sekunden gelb.

Die Uhr habe ich meiner Tochter zum 18. Geburtstag geschenkt.

Herzlichen Glückwunsch vom Papa!

Making of LiquidClock Part 1

Erstes Projekt: Die LiquidClock!

Aufgeschnappt habe ich das Projekt von Christian Aschoff, der schon die QlockTwo als Nachbau einer berühmten Wortuhr entworfen hat.

Die LiquidClock zeigt die Zeit mit Hilfe von WS2812B LED-Stripes an, die über einen ATMEGA328 angesteuert werden.

Christian hat dazu eine kleine Steuerplatine namens BBRTCAD (BareBonesRealTimeClockArduinoDing) entworfen, die alle notwendigen Module für die Steuerung von Uhrenprojekten anhält und mit Hilfe der Arduino-IDE programmiert werden kann:

  • Eine Arduino kompatible Steuerplatine
  • Eine RealTimeClock auf Basis eines DS 1307
  • Ein DCF-77 Modul, um die Uhr in eine funkgesteuerte  Variante zu verwandeln

Ich habe mir auf Christians Seite Liquid-Clock die Aufbauanleitung angesehen und kam dabei auf die Idee, den kompletten Stripe und alle verwendeten Bauteile in eine Schaumpolsterplatte einzuarbeiten. Nachdem es bei PlottFlott bereits fertige Frontfolien gab und ich nicht – wie andere – über Werkzeuge verfüge, mit denen ich ein randloses Gehäuse anfertigen kann, habe ich mich dazu entschlossen, den Aufbau in einem Rahmen eines schwedischen Möbelhauses durchzuführen. Allerdings wollte ich die Komplettfolie von PlottFlott verwenden, um diese auch einmal austauschen zu können. Durch die PE-Platte liegt die Frontfolie – ohne sie verkleben zu müssen – plan an der Glasscheibe an und die Glasscheibe wird wie vorgesehen im Rahmen gehalten.

Die PE-Platte füllt den Rahmen komplett aus.
Die PE-Platte füllt den Rahmen komplett aus.

Wie der Aufbau von statten ging, habe ich hier einmal dokumentiert.

Zunächst musste ich eine geeignete PE-Platte finden. Sie sollte weiß sein, mindestens 25 mm stark und natürlich in den Rahmen passen. Da eine Niederlassung der Firma ratioform direkt in meiner Nähe ist, habe ich dort mal nach Bezugsmöglichkeiten gefragt. Freundlicherweise konnte ich ein Muster von ratioform erhalten. Dafür möchte ich mich noch einmal recht herzlich bedanken.

Die von mir gewählte PE-Platte ist eine spa2 in den Maßen 60 x 60 cm von Ratioform
Die von mir gewählte PE-Platte ist eine spa2 in den Maßen 600 x 600 x 25 mm von ratioform.

Bearbeiten kann man PE-Platten relativ leicht. Sie lassen sich schneiden oder fräsen, so dass ich die gewünschten Formen und Einschnitte mit meinen vorhandenen Werkzeugen durchführen konnte.

Die PE-Platte musste zunächst mal auf die Maße des Rahmens zugeschnitten werden
Die PE-Platte musste zunächst mal auf die Maße des Rahmens zugeschnitten werden.

Der Zuschnitt der Platte auf 500 x 500 mm kann am besten mit Hilfe einer Stichsäge mit Metall-Sägeblatt vorgenommen werden.

Mit dem Rest des Zuschnitts habe ich etwas experimentiert, bevor ich mich an die eigentliche Bearbeitung gewagt habe.

Dann ging es an das Ausfräsen des Kreises. Den habe ich zunächst mit einem Zirkel angezeichnet und dann mit dem schmalen Fräser von Hand ausgefräst. Da der verwendete LED-Strip 1 m ( = 100 cm) lang ist, kann man mit Hilfe der Formel U = 2π r den passenden Radius ausrechnen: r = 100 cm / ( 2π ) ≈ 15,9 cm (genauer 15,9154946 cm, aber das ist bei den verwendeten Werkzeugen ziemlich irrelevant).

Anschließend wird der Bereich für den Anschluss des LED-Strips noch ausgefräst. Dazu habe ich den breiten Fräser genommen. Hier kommt es auch nicht unbedingt auf den Millimeter an.

Um zu prüfen, ob man beim Kreis fräsen sauber gearbeitet hat, zeichnet man die 12, 3, 6 und 9 Uhr Positionen mit einem Edding, legt den Stripe in die Kerbe und prüft, ob die LED im Stripe auf der korrekten Position sind. Die Erste LED des Strips muss genau auf der 12-Uhr Position liegen.

Dabei ist mir aufgefallen, dass ich beim Fräsen des Kreises teilweise auf der mit dem Zirkel angezeichneten Linie gefräst habe. Es hängt natürlich davon ab, wie man den Kreis angezeichnet hat: Eher großzügig oder eher knapp bemessen. Je nachdem muss man also entweder auf der Linie, innen an der Linie oder außen der Linie entlang fräsen. Wenn man den LED-Strip in eine Rundung bringt, muss man daran denken, dass die LED’s auf dem Strip natürlich auch noch etwa 1,5 mm auftragen. Entscheidend ist, dass der Klebestreifen des LED-Strips im Kreisumfang möglichst genau einen Meter lang ist, wenn man den Strip in die Aussparung legt. Für Perfektionisten ist dieser Hinweis eventuell wichtig!

Da  nun der Strip versenkt ist und auch eine Aussparung in der PE-Platte für den Anschluss gemacht ist, geht’s  nun weiter mit der Anschlussbuchse für das Netzteil, dem LDR und den Tasten.

Die Anschlussbuchse habe ich unten, mittig und zentriert in den Rahmen gesetzt. Da das Gewinde etwa 8mm Durchmesser hat, habe ich in den Rahmen zunächst ein 8 mm Loch gebohrt. Ein Holzbohrer ist am besten und wichtig ist: Von außen nach innen bohren, evtl. erst mit einem kleineren Bohrer vorbohren! Danach habe ich auf der Innenseite des Rahmens die Anschlussbuchse noch etwas tiefer versenkt (15 mm Forstnerbohrer, nicht zu tief!). Das ganze sollte dann so aussehen:

Den LDR kann man mit 5 mm ∅ bohren. Was passiert, wenn man zu schnell bohrt, sieht man hier.

immer langsam bohren, sonst gibt’s Fransen!

Nun zu den Tasten: Hier handelt es sich um sogenannte Print-Taster. Diese gibt es mit unterschiedlich langen Stiften. Da ich bei meinem örtlichen Elektronik-Händler 2 verschiedene Längen erhalten habe, musste ich die Versenkungen unterschiedlich tief machen. Dazu aber später noch mehr.

Zunächst brauchen wir 3 Löcher mit einem 4 mm ∅ Bohrer an geeigneter Stelle. Ich habe diese Bohrungen an der Seite des Rahmens gemacht. Da die 3 Tasten die Funktionen

  • Moduswechsel (Mode)
  • Stunden (H+)
  • Minuten (M+)

haben, habe ich diese mit etwas Abstand angeordnet, so dass die Taste für Mode etwas weiter von den anderen Tasten weg ist.

Nach den 4 mm Bohrungen muss man auf der Rahmeninnenseite die Tasten entsprechend der Stiftlänge mit dem 15 mm Forstnerbohrer versenken. Um die richtige Tiefe zu erhalten, schneidet man sich aus dem Passepartoutkarton des Rahmens zwei Streifen ab und legt diese untern den Rahmen. Dieser Abstand ist wichtig, damit man die Tasten von Außen auch gut drücken kann. Ein paar Bilder sagen hier mehr als Worte.

Wir brauchen 4 Kabel für die Tasten: 3 mal Signal, einmal gemeinsame Masse. Wie man diese Kabel am sichersten an die Print-Taster anlötet, sieht man hier.

Danach werden die Tasten mit Heißkleber vergossen. Wichtig dabei ist, dass man den Heißkleber nicht zu dick aufträgt, da man ja noch die Glasscheibe einsetzen muss. Ist im Bild nicht zu sehen, hat mich aber eine Menge Nerven gekostet, die Scheibe einzusetzen. Die Kabel sollte man so lang lassen, dass man die PE-Platte noch um mindestens 180° zur Seite wegklappen kann. Auch hier wieder ein paar Bilder, die mehr sagen als… (lassen wir das):

Im letzten Bild sieht man auch die Kabelführung in der PE-Platte.

Noch ein paar Aussparungen in die Platte gemacht für den DCF-Empfänger (ich nehme immer den von Conrad bei meinen Projekten) und den BBRTCAD, dann ist man mit dem mechanischen Aufbau eigentlich schon fertig.

Jetzt noch gemäß des Anschlussplans alle Kabel an den BBRTCAD anschließen, dann sind wir fertig.

In die Rückwand kommen jetzt noch ein paar Bohrungen zum Aufhängen der Uhr.

3 Löcher zum Aufhängen
3 Löcher zum Aufhängen

Wie das Endergebnis aussieht zeige ich euch dann demnächst, wenn auch die Frontfolie geliefert ist. Evtl. auch mit Video.