Eigener Server für Kalender und Kontakte

Kalender und Kontakte sollten auf allen Geräten, sei es mobil oder stationär, abrufbar und synchron sein. Das spricht dafür, dass sie über Netzwerk oder sogar das Internet abgeglichen werden. Müssen diese sensiblen Daten aber gleich in der Cloud eines großen Anbieters wie Google und Co landen?

Wenn man dies nicht will, bieten sich Lösungen auf CalDav– und CardDav-Technologie an. Beide Protokolle setzen auf WebDAV nach RFC 4918 auf. CalDAV synchronisiert Kalenderdaten nach RFC 4791, CardDav hingegen Kontakte nach RFC 6352.

Bei der Auswahl des Servers für beide Protokolle hat man viel Auswahl. Die Wikipedia bietet eine Aufstellung von Möglichkeiten.

Server einrichten

Für den Server habe ich ich mich für Radicale entschieden. Zusätzlich soll als Frontend InfCloud verwendet werden um auch mit dem Browser von beliebigen Endgeräten auf die Kalender und Adressen zugreifen zu können.

Thomas Queste hat mit dem Docker Image tomsquest/docker-radicale eine einfache Möglichkeit geschaffen, diese Software zu verwenden.

Zunächst legt man Verzeichnisse an:

  • /data/cal/config – für die Konfigurationsdatei und die Datei mit den Nutzern
  • /data/cal/data – für die eigentlichen Kalender- und Adress-Daten

An Konfigurationsdateien benötigt man die Datei /data/cal/config/config mit folgendem Inhalt:

[server]
hosts = 0.0.0.0:5232

[encoding]

[auth]
type = htpasswd
htpasswd_filename = /config/users
htpasswd_encryption = bcrypt

[rights]

[storage]
filesystem_folder = /data/collections

[web]
type = radicale_infcloud

[logging]

[headers]

Die Datei /data/cal/config/users wird mit den üblichen Tools zur Verwaltung von .htaccess-Dateien modifiziert: htpasswd. Wichtig ist mit der obigen Konfiguration der Parameter -B zur Aktivierung der bcrypt-Verschlüsselung:

htpasswd -B /data/cal/config/users $username

Anschließend muss der Docker-Container angelegt und ausgeführt werden:

docker run \
    -d \
    --name radicale \
    -p 5323:5232 \
    -v ~/tmp/cal_data:/data \
    -v ~/tmp/cal_config:/config:ro \
    tomsquest/docker-radicale

Natürlich sollte man im produktiven Einsatz eine TLS-gesicherte Verbindung auf Port 443 verwenden!

Wenn alles funktioniert sollte man unter http://localhost:5232/.web auf die Weboberfläche von Radicale zugreifen können. Als Logins dienen die Accounts, die in der Datei users angelegt wurden. Dort kann man nun alle benötigten Collections, wie Adressbücher, Kalender und Aufgabenlisten anlegen.

Clients

Clients wurden für eine möglichst große Anzahl von Plattformen untersucht.

Browser

InfCloud (in Version 0.13.1) läuft laut Hersteller in allen HTML5 fähigen Browsern wie Safari/Mobile Safari, allen Webkit-basierten, iCab, Firefox, Opera (15+) und Chrome. Zugegriffen werden kann auf InfCloud unter http://localhost:5232/.web/infcloud/.

iOS

Funktioniert direkt ohne weitere Software, was mich positiv überraschte.

Unter EinstellungenAccounts & Passwörter → Account hinzufügen → Andere → CalDAV-Account hinzufügen konfiguriert man den Zugriff auf die Kalender:

Server ist hier der Hostname, unter der Radicale zu erreichen ist. Benutzername und Passwort sind wie in der Users-Datei angegeben und die Beschreibung ist ein beliebiger Text.

Analog verfährt man mit dem Einbinden der Adressbücher. Unter EinstellungenAccounts & Passwörter → Account hinzufügen → Andere → CardDAV-Account hinzufügen konfiguriert man den Zugriff auf die Adressbücher. Die Werte sind analog zu denen bei den Kalendern.

Android

Google macht es uns bei Android etwas schwerer, man will wohl die eigene Cloud mal wieder pushen.

Aber mit CalDAV Sync Free Beta erhält man eine Open-Source Software, die weiterhilft. Ist die Software installiert, so kann man unter EinstellungenKonten → Konto hinzufügen mit der Option CalDav Sync Adapter den Zugang zu den Kalendern einrichten.

Der Benutzer und das Passwort sind die Werte, die auch für das Login in InfCloud verwendet werden. Die URL findet man in der Web-UI von Radicale und sollte einfach per Mail auf das Android Gerät kopiert werden. Anschließend findet man unter EinstellungenKonten → CalDav Sync Adapter den neu eingerichteten Kalender und muss bei diesen noch die Synchronisierung aktivieren:

Jetzt sollte der eingerichtete Kalender in der Kalender App eingebunden sein.

Kontaktdaten via CardDav können ebenso nur mit Zusatzsoftware eingebunden werden. Hier CardDAV-Sync free eine kostenlose Option, die leider nicht frei (wie in freier Software) ist. Auch hier muss man wieder die komplette URL aus der Radicale Web-UI verwenden (analog zur Lösung für CalDAV-Daten). Anschließend können Kontakte zwischen Radicale synchronisiert werden und auch auf dem Android Gerät wie gewohnt erstellt werden.

Desktop

macOS

Unter macOS gibt es, wie unter iOS auch, die Möglichkeit direkt mit Bordmitteln auf Adress- und Kalenderdaten zuzugreifen. In den Einstellungen gibt es Optionen sowohl für CalDAV als auch für CardDAV.

Die Einrichtung findet analog zu iOS statt (hier sieht man inwieweit iOS und macOS sich gleichen).

Linux/Windows

Hier kann Thunderbird mit den beiden Add-ons Lightning (getestet in Version 6.2) und CardBook (getestet in Version 31.2) alle notwendigen Funktionen bereitstellen.

Lightning konfigurieren

Hier wählt man beim Anlegen eines neuen Kalenders die Option Im Netzwerk und als Format CalDAV. Auch hier muss man die URL des Kalenders aus der Web-UI von Radicale entnehmen und einfügen. Anschließend definiert man einen lokalen Namen und legt eine Farbe fest. Im Authentifizierungsdialog trägt man Nutzernamen und Passwort ein. Die Authentifizierung muss pro Server nur einmal vorgenommen werden.

CardBook konfigurieren

Beim Anlegen eines neuen Adressbuches wiederum die Option Im Netzwerk und als Format CardDAV. Dann kopiert man erneut die URL des Adressbuchs und authentifiziert sich. Wichtig das vCard-Format muss auf 3.0 geändert werden! Ansonsten können die erstellten vCards nicht auf allen Clients (z.B. InfCloud) bearbeitet werden.

Windows 10

Unter Windows 10 kann man sich mit folgendem Trick behelfen: https://www.ctrl.blog/entry/how-to-win10-webdav-syncengine (Allerdings ohne Garantie für zukünftige Updates).

 

TinkerForge: Einstieg mit Master Brick 2.1, WIFI Master Extension 2.0 und Voltage/Current Bricklet 2.0

TinkerForge ist eine deutsche Firma aus Schloß Holte-Stukenbrock, die sich seit 2011 bemüht, die Arbeit mit eingebetteten Systemen zu vereinfachen. Ein Stecksystem erübrigt den Griff zum Lötkolben und  detaillierte Kenntnisse in Elektronik werden überflüssig. In diesem Artikel möchte ich testen, in wie weit dies gelungen ist und meine persönliche Erfahrung beschreiben.

Einführung

TinkerForge setzt konsequent auf den Open Source Gedanken und veröffentlicht den Quellcode und weitere Informationen zu den einzelnen Produkten im Firmenaccount auf Github in aktuell 178 Repositories.

Um das Ziel der Vereinfachung zu erreichen, setzt TinkerForge auf ein Baukastensystem aus Bricks, Bricklets und Master Extensions.

Bricks und Master Extensions besitzen eine einheitliche Grundfläche von 4x4cm und werden über den Stack Connector zu Stapeln verbunden. Der wichtigste Brick ist dabei der Master Brick, dieser erfüllt mehrere Aufgaben. Zum einen ermöglicht er den Anschluss von bis zu 4 Bricklets,  bietet die direkte Kommunikation via USB zu einem PC und dienst als Master der Kontrolle des Stapels (nur der Master Brick, um unteren Ende des Stapels dient als tatsächlicher Master, die anderen bieten dann nur  den Anschluss von weiteren maximal 4  Bricklets). Weitere Bricks erlauben den direkten Anschluss von Gleichstrommotoren, Modellbauservos und Schrittmotoren oder dienen als 9-Achsen Lagesensor (IMU Brick). In der Dokumentation findet sich eine Liste der Bricks neben einer Liste der Master Extension.

Bei den Bricklets wird bewusst auf ein einheitliches Format verzichtet, da so ganz unterschiedliche Sensoren, Aktoren, Konverter zu anderen Bussystemen und verschiedenen Mensch-Maschine-Schnittstellen verbunden werden können. Eine vollumfängliche Liste der Bricklets findet man sich in der Bricklet-Dokumentation. Verbunden werden die Bricklets mit vorkonfektionierten Kabeln unterschiedlicher Längen von 6cm bis zu 2m.

Allen Modulen gemein ist ein Raster der Befestigungslöcher von 5mm, zur Befestigung bietet Tinkerforge Montageplatten für den schnellen Aufbau auf dem Schreibtisch an.

Tinkerforge bietet aktuell für 14 Sprachen (davon 3 als spezielle Ausprägungen für mobile Geräte) fertig APIs an. Diese basieren alle auf dem TCP/IP Protokoll, deshalb sollte eine Adaption für weitere Sprachen durchführbar sein (Swift fehlt zum Beispiel in der Liste der unterstützten Sprachen bisher).

Persönliche Erfahrung

Für den Einstieg entschied ich mich für folgende 3 Module:

Das Ziel ist die kombinierte Messung der von einer Solarzelle gelieferten Spannungs- und Stromwerte und der Transfer in ein Grafana.

Bestellt habe ich direkt bei TinkerForge, geliefert wurde ohne Aufschlag bereits am nächsten Tag.

Installation des Brick Daemon (brickd)

Der Brick Daemon abstrahiert als Systemdienst die Kommunikation zwischen den APIs und dem Master Brick über USB. Den Quellcode findet man im brickd-Repository und Pakete für Debian-artige Distributionen zum Download auf tinkerforge.com.

Allerdings ist die Standardkonfiguration des suboptimal, da auf allen IP Adressen des Rechners ohne Authentifizierung gelauscht wird. Hier sollte man sich doch eher auf localhost 127.0.0.1 beschränken. Dies kann nachträglich in der Datei /etc/brickd.conf mit der Option listen.address angepasst werden. Zusaetzlich habe ich einen Pull-Request erstellt, der das Default anpasst.

Nach der Einrichtung der WIFI Master Extension kann jedoch direkt deren IP Verbindung genutzt werden und der brickd wird obsolet.

Installation des Brick Viewer (brickv)

Der Brick Viewer ermöglicht den Zugriff auf auf lokal angeschlossene Bricks über USB und auch per IP auf entfernte Bricks. Auch hier ist der Quellcode im entsprechenden brickv-Repository zu finden, deb-Pakete finden sich als Downloads auf tinkerforge.com.

Leerer Master Brick
Setup-Reiter eines Master Brick ohne weitere Module

Der Brick Viewer zeigt bei einem einzelnen Master Brick natürlich noch nicht viele Informationen an:

Update Dialog
Dialog zum Aktualisieren der Firmwares

Allerdings ist schon jetzt eine Verbindung via USB möglich und es kann zum Beispiel ein Update der Firmware vorgenommen werden (Changelog).

Schließt man nun den Voltage/Current Bricklet 2.0 an einen beliebigen Port des Master Bricks an, so wird dieser automatisch erkannt.

Master Brick mit Voltage/Current Bricklet 2.0
Setup-Reiter eines Master Brick mit angeschlossenem Voltage/Current Bricklet 2.0

Hat man nun der Beschriftung des Bricklets entsprechend die Stromquelle und den Verbraucher angeschlossen, so kann man auf dem entsprechendem Reiter sofort mit der Messung beginnen.

Erste Messung
Einfache Graphen im Brick Viewer

Über die Funktion “Data Logger” im Setup-Reiter kann bereits jetzt mit einer dauerhaften Aufzeichnung von Daten in eine CSV-Datei begonnen werden. Allerdings ist eine USB Verbindung für eine Messung am Fenster (mit der Solarzelle) nicht praktikabel.

Eine Möglichkeit wäre eine der vielen Bastelplatinen mit USB und WLAN zu verwenden oder man greift zur WIFI Master Extension 2.0. Diese ersetzt die USB-Verbindung und den lokalen Brick Daemon durch ein WLAN Modul.

Aufbau des Stapels

Die Bricks und Master Extensions werden über die mitbestellten Befestigungskits verschraubt, nachdem die Module korrekt ausgerichtet worden (man beachte die weiß markierten Ecken!).

Master Brick und WIFI Master Extension 2.0
Stapel aus Master Brick und WIFI Master Extension 2.0

Auch die WIFI Master Extension wird direkt im Brick Viewer erkannt:

WIFI Konfiguration
Konfiguration der WIFI Master Extension 2.0 im Brick Viewer

Nach der Konfiguration als WLAN-Client (General und Mode) muss noch das richtige WLAN ausgewählt werden. Anschließend kann über “Show Status” geprüft werden, ob die WLAN Einrichtung erfolgreich war und welche IP der Stapel bekommen hat. Die kann man dann zur Kommunikation zwischen Brick Viewer und dem Stapel verwenden.

Nutzung der Python API

Das Modul installiert man einfach mit pip:

pip install --user tinkerforge

Folgendes Skript öffnet zunächst eine IPConnection zu dem aufgebauten Stapel über die WIFI Master Extension. Anschließend wird auf das angeschlossene Bricklet zugegriffen und sekündlich die Werte für Spannung, Stromstärke und Leistung ausgegeben.

HOST = "192.168.178.203"
PORT = 4223
UID = "FKC"

from tinkerforge.ip_connection \
    import IPConnection
from tinkerforge.bricklet_voltage_current_v2 \
    import BrickletVoltageCurrentV2
from time import sleep

if __name__ == "__main__":
    ipcon = IPConnection() 
    ipcon.connect(HOST, PORT) 

    vc = BrickletVoltageCurrentV2(UID, ipcon) 

    while True:
        voltage = vc.get_voltage()/1000.
        current = vc.get_current()/1000.
        power = vc.get_power()/1000.

        print(str(voltage) + " V " + \
              str(current) + " A " + \
              str(power) + " W")
        sleep(1)

Weitere Dokumentation zur API findet sich auf der Webseite von Tinkerforge.

Fazit

Mit den Bricks und Bricklets von TinkerForge erhält man ein einfach zu verwendendes Modulsystem. Die Verarbeitung der Module wirkt qualitativ hochwertig. Dies und die einfache Handhabung durch die unterstützende Software rechtfertig in meinen Augen den leicht höheren Preis. Auch die Auswahl der bereits jetzt existierenden Module lädt zu weiteren Experimenten ein.

‘git grep’ oder wie finde ich nochmal, was ich noch tun muss?

In meinem laufenden Projekt homekit_python haben sich inzwischen doch 2 oder 3 TODOs angesammelt. Wie findet man am schnellsten die TODOs die sich in Dateien befinden, die von git verwaltet werden?

Die Antwort ist einfacher, wie ich zunächst annahm: git bietet mit dem Kommando git grep bereits alles was ich benötige:

git grep TODO

Die Ausgabe umfasst in dieser einfachsten Form wie von grep gewohnt alle Treffer:

Weitere git-Kommandos findet man im git Reference Manual.

FPGA: Erste Schritte

Um mal wieder über den berühmten Tellerrand zu blicken will ich mich mal mit etwas neuem beschäftigen. Die Wahl fiel auf FPGAs. Während des Studiums habe ich mich leider durch Wahl eines alternativen Praktikums um eine erste Erfahrung gebracht.

Für einen ersten Einstieg benötigt man nur Software, keine Hardware. Die Software (zumindest von Intel/Altera kann man gratis herunterladen. Dazu unten mehr. Da ich das am Anfang nicht wusste, habe ich über Amazon die im Folgenden genannten Produkte erworben.

Einkauf

Gesamtkosten: keine 30€, da der Klon deutlich günstiger als das Original mit fast 400€ ist.

Erste Erfahrungen

Zunächst sollen einige wichtige Erkenntnisse aufgeführt werden. Zu den beiden genannten Softwarepaketen:

  1. Der Cyclone II wird bis maximal Quartus II Web Edition 13.0sp1  unterstützt. Diese kann kostenlos mit einem myAltera-Account heruntergeladen werden (4.8GB). Nach der Installation sind es ca. 16 GB, wobei man hier beim Installationsumfang sicher sparen kann. Neuere Versionen unterstützen nur neuere FPGAs. Gestartet wird das Programm auf 64-bit Systemen über ./bin/quartus –64bit aus dem Installationsverzeichnis.
  2. JTAG einrichten: unter Ubuntu 17.10 benötigt man zusätzliche udev-Regeln (Datei /etc/udev/rules.d/usbblaster.rules):
    SUBSYSTEM=="usb",ATTR{idVendor}=="09fb",ATTR{idProduct}=="6001",MODE="0666"
    SUBSYSTEM=="usb",ATTR{idVendor}=="09fb",ATTR{idProduct}=="6002",MODE="0666"
    SUBSYSTEM=="usb",ATTR{idVendor}=="09fb",ATTR{idProduct}=="6003",MODE="0666"
    SUBSYSTEM=="usb",ATTR{idVendor}=="09fb",ATTR{idProduct}=="6010",MODE="0666"
    SUBSYSTEM=="usb",ATTR{idVendor}=="09fb",ATTR{idProduct}=="6810",MODE="0666"

    Diese ermöglichen den Zugriff auf für nicht root Nutzer. Anschließend kopiert man die Board-Descriptions nach /etc/jtagd:

    cp $INSTALLDIR/linux64/pgm_parts.txt /etc/jtagd/jtagd.pgm_parts
    

    Weiter Informationen findet man unter bitsnbites.eu.

  3. Mit ModelSim-Intel FPGA Edition 10.5c kann man auch im myAltera-Account herunterladen (3.1GB). Nach der Installation sind es ca. 7 GB. Vor dem Starten wird noch die Bibliothek freetype in Version 2.4.12 benötigt. Hinweise zur Installation liefert das Armadeus Project Wiki und ein Blog. Gestartet wird anschließend mit ./bin/vsim aus dem Installationsverzeichnis.

Spezifisch zu dem Basisboard gibt es noch folgendes zu sagen:

  1. Das Basisboard muss mit 5V über den entsprechenden Anschluss versorgt werden, sonst wird es nicht über den USB Blaster beim JTAG Scan erkannt. Hierbei liegen die 5V innen an! Es handelt sich um einen 2.1mm/5.5mm Hohlstecker. Update: Die Stromversorgung ist auch über P8 möglich, hier ist der 5V Pin weiter in Richtung Platinenmitte und GND Richtung Rand platziert.
  2. Wichtige Pins sind wie folgt belegt:
    Pin-NummerPin-Funktion
    Pin 3D2 (LED, Output)
    Pin 7D4 (LED, Output)
    Pin 9D5 (LED, Output)
    Pin 17CLK (50 MHz, Input)
    Pin 144Taster (Input)
    Pin 7310uF nach GND, 10K an Vcc
    Pin 26an 1.2V VCC angeschlossen
    Pin 27an GND angeschlossen
    Pin 80an GND angeschlossen
    Pin 81an 1.2V VCC angeschlossen
    Hier ist beim Anschluss von an weiterer Hardware entsprechend Vorsicht geboten.
  3. Der Schaltplan des Basisboards befindet sich u.a. hier:

    Schaltplan des Basisboards (Quelle: http://artofcircuits.com)

Erstes Projekt

Wir starten Quartus II und wählen den “New Project Wizard“. Zunächst wird das Projekt benannt:

Erster Schritt des Wizards

Anschließend kann man bereits existierende Dateien hinzufügen (wir haben allerdings noch keine):

Schritt 2 des Wizards

Die Auswahl des FPGAs (hier die Selektion für den FPGA auf dem Basisboard):

Schritt 3 des Wizards

Einige Informationen über den vorhandenen FPGA werden hier auch aufgezählt:

  • 8256 LEs (Logic Elements) sind die Basisbausteine, im Detail beschrieben auf Seite 2-2 im Cyclone II Architecture Dokument. Jeweils 16 davon werden zu einem LAB (logic array block) zusammengefasst (516 sind vorhanden).
  • 85 User I/Os (Ein/Ausgänge, die für den Entwickler verfügbar sind)
  • 165888 Bit Speicher in 36 M4K Blöcken
  • 36 9×9-Bit Mulitplizierwerke oder alternativ 18 18×18 Multiplizierwerke
  • 2 PLLs
  • 8 globale Takte

Nun hat man ein leere Projekt erzeugt. Mit  “File” und “New” erstellt man eine neue VHDL Datei.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
 
entity vhdl_example_1 is
 port( 
  clk: in std_logic;
  led: out std_logic
 );
end vhdl_example_1;
  
architecture bhv of vhdl_example_1 is
 signal count: integer := 1;
 signal tmp: std_logic := '0'; 
begin
 process(clk) begin
  if(clk'event and clk = '1') then
   count <= count + 1;
   if (count = 25000000 ) then
    tmp <= NOT tmp;
    count <= 1;
   end if;
  end if;
  led <= tmp;
 end process;
end bhv;

Diese speichert man unter dem Namen vhdl_example_1.vhd ab. Mit Processing und Start Compilation kann man das Übersetzen starten. Unter Assigments und Pin Planner starten wir die Zuordnung der unter Port definierten Ein-/Ausgänge. Folgende Zuordnung muss vorgenommen werden:

  • clk auf Location PIN 17
  • led auf Location PIN 3
Ausschnitt der konfigurierten Pins

Als letzten Schritt muss der FPGA noch ueber den JTAG Anschluss programmiert werden. Dazu verwendet man den unter Tools den Programmer. Zunächst wählt man unter Hardware Setup den USB-Blaster aus. Als Datei fügt man  output_files/vhdl_example_1.sof hinzu und als Device den FPGA des Basisboards. Anschließend kann man mit Start die Programmierung starten.

Einstellungen im Programmer

Sollte dies nicht (mehr) funktionieren, kann es helfen den USB-Blaster kurz vom USB zu trennen.

Hat alles funktioniert, sollte die LED D2 mit 1Hz blinken:

Update 2. März 2018 zum Thema alternative Stromversorgung.

Update 31. März 2018 zum Thema JTAG einrichten

Brother DCP-9017CDW und Linux

Das alte Faxgerät meines Vater ging leider kaputt und wurde zuletzt eh nur noch als Kopierer verwendet. Als Ersatz wurde ein Brother DCP-9017CDW auserkoren, da dieses Gerät:

  1. ein duplexfähigen Farblaser zur Ausgabe verwendet (trocknet einfach nicht ein),
  2. einen moderaten Anschaffungspreis besitzt,
  3. per WLAN auch mit Linux als Drucker verwendet werden kann und
  4. über ein einfaches Touch Display bedient werden kann.

Kurz um, das Gerät scheint das richtige zu sein, zumal auch eine Funktion “Scan2Email” auf der Funktionsliste steht. Leider sagt das Kleingedruckte “Benötigt Brother-Software” und verweist auf einen optionalen kostenlosen Download für Linux aus dem Brother Solutions Center. Ebenso leider existiert dann kein Download für Linux im Brother Solutions Center (Stand 25.12.2017). Ergo kein offizieller Weg für Scan2Email. Na danke.

Ohne Brother Software kann das Gerät allerdings auf (lokale) FTP-Server scannen. Lokal deshalb, da FTP als unsicher einzustufen ist (Link, Link, …).

Die Idee ist nun: vom Brother DCP-9017CDW wird in ein FTP-Verzeichnis pro Email-Adresse gescannt. Auf dem FTP-Server wird auf eingehende Dateien reagiert und diese per Mail versendet.

Folgende Software wurde ausgewählt:

  • vsftpd als FTP-Server,
  • mpack zum Versand der Dateien als Anhang,
  • exim4 mit Smarthost zum Versand der Mails und
  • incron zum Reagieren auf neue Dateien.

Zunächst erlaubt man dem vsftpd in seiner Konfiguration das Schreiben von Dateien (write_enable=YES) sowie lokale User (local_enable=YES). Somit kann auf dem DCP-9017CDW testweise auf den FTP-Server gescannt werden.

Anschließend exim so einrichten, dass er Mails nach außen versenden kann. Das passiert in diesem Szenario mit einem Smarthost. Dann sollte man testen, ob mpack auch Anhänge versenden kann:

mpack -s SUBJECT /PATH/TO/FILE MAILADRESSE

Kurz danach sollte die Datei als Anhang eintreffen.

Abschließend noch incron konfigurieren, damit auf neue Dateien reagiert werden kann:

  • den Nutzernamen, unter dem per FTP die Dateien abgelegt werden, in der Datei /etc/incron.allow vermerken
  • mit incrontab -e pro Verzeichnis bzw. Email Adresse eine Zeile der Form
    $PFAD IN_CLOSE_WRITE $Script $@/$# $MAIL

    eintragen

Das Script übergibt mpack die Datei und die Mailadresse und löscht die Datei nach dem Versand.

Et voilà, Scan2Mail funktioniert doch.

Thread Dumps – auch für Python

Thread Dumps sind Momentaufnahmen des Aufruf-Stacks für jeden Thread einer laufenden multi-thread Anwendung. Dies ist in vielen Situationen zur Analyse hilfreich. Diese gestaltet sich gerade bei multi-thread Anwendung meist komplizierter.

Für Java gibt es das Programm jstack (u.a. mit jps im JRE enthalten) um Thread Dumps zu erzeugen.

Unter Python kann ein ähnliches Verhalten (getestet unter Linux) mit einem kleinen Umweg über einen Signal-Handler erreicht werden:

...
import faulthandler 
import signal
import os
...

def handler(signum, frame):
  file ='/tmp/threads'
  print('Writing thread dump to ', file)
  with open(file, 'w') as f:
    faulthandler.dump_traceback(file=f, all_threads=True)

...
if __name__ == '__main__':
  with open('/tmp/pid', 'w') as f:
    f.write(str(os.getpid()))
  signal.signal(signal.SIGUSR1, handler)
  ...

Nach dem Starten des Programms kann man über die PID aus /tmp/pid einen Thread Dump erzeugen:

kill -USR1 `cat/tmp/pid`

Dieser sieht exemplarisch so aus (extra in kleinerer Schriftart um die Zeilen ohne Umbrüche zu erhalten):

Thread 0xb3ccb460 (most recent call first):
 File "/home/jlusiardi/.local/lib/python3.4/site-packages/zeroconf.py", line 1102 in run
 File "/usr/lib/python3.4/threading.py", line 920 in _bootstrap_inner
 File "/usr/lib/python3.4/threading.py", line 888 in _bootstrap

Thread 0xb44ff460 (most recent call first):
 File "/usr/lib/python3.4/socketserver.py", line 154 in _eintr_retry
 File "/usr/lib/python3.4/socketserver.py", line 236 in serve_forever
 File "/home/jlusiardi/sources/smarthome/homekit_link/__init__.py", line 142 in run
 File "/usr/lib/python3.4/threading.py", line 920 in _bootstrap_inner
 File "/usr/lib/python3.4/threading.py", line 888 in _bootstrap

Thread 0xb4cff460 (most recent call first):
 File "/home/jlusiardi/sources/smarthome/influxdb/__init__.py", line 109 in run
 File "/usr/lib/python3.4/threading.py", line 920 in _bootstrap_inner
 File "/usr/lib/python3.4/threading.py", line 888 in _bootstrap

Thread 0xb6025460 (most recent call first):
 File "/usr/lib/python3.4/socketserver.py", line 154 in _eintr_retry
 File "/usr/lib/python3.4/socketserver.py", line 236 in serve_forever
 File "/home/jlusiardi/sources/smarthome/homematic/callback.py", line 42 in run
 File "/usr/lib/python3.4/threading.py", line 920 in _bootstrap_inner
 File "/usr/lib/python3.4/threading.py", line 888 in _bootstrap

Current thread 0xb6fb6300 (most recent call first):
 File "./main.py", line 19 in handler
 File "/usr/lib/python3.4/cmd.py", line 126 in cmdloop
 File "/home/jlusiardi/sources/smarthome/cli/__init__.py", line 32 in cmdloop
 File "./main.py", line 50 in <module>

Auch hier bieten sich verbesserte Analysemöglichkeiten analog zu Java.

SanDisk iXpand 128 GB

Ich bin iPhone-User und kann mich an Android einfach nicht gewöhnen. Allerdings bin ich auch preisbewusst und habe mich dieses Jahr erstmals für ein neues iPhone SE mit 32GB entschieden. Der Speicherplatz ist eigentlich ausreichend.

Eigentlich…

Im Urlaub fallen ja dann mal doch mehr Bilder und Videos an, da können 32GB schon mal knapp werden. Alles in die Cloud? Laptop mit Windows oder OS X mitnehmen? Kann man sich dank des SanDisk iXpand 128 GB sparen. Dank iOS-App kann man u.a. Bilder und Videos vom iPhone auf den Stick sichern. Nach einem Backup lassen sich die gesicherten Dateien automatisch aus der App heraus löschen. Ein weiterer Vorteil: auch Linux-User kommen so an die Bilder und Videos des iPhones.

Fazit: gute, einfache Möglichkeit schnell Bilder und Videos vom iPhone zu sichern.

Docker und IPv6

Zu meinem Root-Server gab es ein /64-IPv6 Netz (z.B. 2a03:4000:15:3b7/64)  und somit mehr als genug Adressen. Doch wie kann ich Docker-Container unter über diese Adressen ansprechen?

Zunächst fügt man eine IPv6-Adresse aus dem Netz der Netzwerkkarte hinzu:

ip -6 a a 2a03:4000:15:3b7::3/64 dev eth0

Dann startet man einen Container und ruft die IPv4 Adresse aus dem Docker-internen Netz ab:

docker run --name testnginx -d nginx
docker inspect --format '{{ .NetworkSettings.IPAddress }}'\
    testnginx

Anschließend leitet man mit socat die IP-Pakete von der IPv6-Adresse an die IPv4-Adresse des Containers weiter:

socat TCP6-LISTEN:80,reuseaddr,fork,bind=[2a03:4000:15:3b::3]\
    TCP4:172.17.0.15:80

Nun kann man direkt auf den Port des Containers über IPv6 zugreifen.

Influxdb und Grafana

Aus meinem beruflichen Umfeld ist mir Grafana als Lösung zur grafischen Aufbereitung gut bekannt. Daten beziehen wir klassisch aus Graphite.

Für ein Projekt habe ich nun die Daten über öffentliches Netz (also das Internet) in die Datensenke einliefern müssen. Zunächst auch hier an Graphite gedacht, jedoch ergab sich schnell die Überlegung, das der Graphite Port 2003 (hier lauscht der Carbon Daemon) jedwede Daten ohne Authentifizierung annimmt. In einem  öffentlichen Netz sicher kein akzeptabler Zustand, da hier jeder mit Kenntnis von Port und IP beliebige Stördaten einliefern kann. Also auf die Suche nach Alternativen.

InfluxDB bietet laut db-engines.com  als Berechtigungskonzept mit einer “einfache[n] Rechteverwaltung mit Benutzeraccounts” mehr als Graphite. Auch verspricht die Implementierung in Go mehr Performance. Grund genug, sich InfluxDB näher anzusehen.

InfluxDB

Dank des offiziellen Docker Images ist InfluxDB schnell probeweise gestartet. Hinweise liefert die Seite des Docker-Hub. Zunächst wird die Standardkonfiguration extrahiert:

docker run --rm influxdb influxd config > influxdb.conf

In dieser Datei muss die Option auth-enabled nun aktiviert werden:

...
[http] 
...
auth-enabled = true
...

In Kombination mit meinen beiden Projekten docker_nginx_auto_proxy und docker_ssl_endpoint kann man nun einen Docker Container starten, der Daten über TLS abgesichert entgegen nimmt:

docker run --name=influxdb_1 -d \
 -e PROXY_DATA=server_names:$INFLUXDOMAIN,port:8086 \
 -v /data/influxdb/data:/var/lib/influxdb \
 -v /data/influxdb/conf:/etc/influxdb/influxdb.conf:ro \
 influxdb -config /etc/influxdb/influxdb.conf

Nun müssen wir mindestens einen Admin-Nutzer anlegen. Zunächst verbinden wir uns auf die InfluxDB-CLI:

docker run --rm --link=influxdb_1 -it influxdb influx -host influxdb_1

Anschließend legt folgendes Statement den Admin-Nutzer bofh an:

CREATE USER bofh WITH PASSWORD 'rrzs42' 
  WITH ALL PRIVILEGES

Anschließend die CLI beenden und beim Neuverbinden zusätzlich die Parameter username und password zur Authentifizierung verwenden. Weitere Informationen zur Nutzerverwaltung von InfluxDB findet man in der offiziellen Dokumentation.

Eine Datenbank sollte in der CLI ebenfalls erstellt werden:

CREATE DATABASE datensenke

Testweise können nun bereits Daten eingeliefert werden:

curl -X POST -u bofh:rrzs42 \
  --data-binary 'wert,key=value wert=42.23'\
  'https://$INFLUXDOMAIN/write?db=datensenke'

Die genaue Beschreibung über das Schreiben von Daten findet man in der offiziellen Dokumentation.

Grafana

Für Grafana gibt es ebenfalls ein offizielles Docker-Image. Der erste Schritt ist das Extrahieren der Konfiguration:

docker run --rm --name grafana grafana/grafana
docker cp grafana:/etc/grafana/grafana.ini .

Die wichtigste Anpassung der Konfiguration bezieht sich auf das Abschalten des selbständigen Anmeldens neuer Nutzer (allow_sign_up = false in der Kategorie users). Somit ist nur noch der Administrator (Login: admin) in der Lage, neue Nutzer anzulegen.

Gestartet wird der Grafana-Container mit folgendem Kommando:

docker run --name=grafana -d \
    -e PROXY_DATA=server_names:$GRAFANADOMAIN,port:3000 \
    -v /data/grafana/lib:/var/lib/grafana/ \
    -v /data/grafana/conf:/etc/grafana/grafana.ini \ 
    -e "GF_SERVER_ROOT_URL=https://$GRAFANADOMAIN" \
    -e "GF_SECURITY_ADMIN_PASSWORD=s3cr3t" \
    grafana/grafana

Nun kann die Grafana-Instanz unter  https://$GRAFANADOMAIN aufgerufen werden und der Login funktioniert mit den Credentials admin:s3cr3t.

Der nächste Schritt sollte das Ändern des Passworts des Administrators sein und das Anlegen neuer Nutzer sein. Dies geschieht unter Grafana-MenuAdminGlobal Users.

Um wie die Daten aus InfluxDB in Grafana nutzen zu können, legt man eine Datenquelle unter Grafana-MenuData Sources an. Die Einstellungen für InfluxDB sind in unserem Fall:

  • Type: InfluxDB
  • URL: https://$INFLUXDOMAIN
  • Access: Proxy
  • Http Auth: With Credentials
  • InfluxDB Details:
    • Database: datensenke
    • User: bofh
    • Password: rrzs42

Jetzt sind wir in der Lage, über Dashboards wie gewohnt Graphen an zu legen. Beispielsweise:Et voilà, flexible und ansehnliche graphische Aufbereitung von Zeitseriendaten.

Dynamische IP – Reagieren auf Änderungen

Als DSL Nutzer kommt man hierzulande meist nicht in den Genuss einer statischen IPv4 Adresse sondern bekommt regelmäßig eine andere IPv4 von seinem Provider zugewiesen. Als Nebeneffekt wird dadurch das Anbieten von Serverdiensten an Heimanschlüssen oder auch der Betrieb eines IPv6 Tunnels erschwert.

Die FRITZ!Box bietet Unterstützung für einige DDNS-Provider, manchmal möchte man aber auch einfach ein Skript ausführen. Den möglichen Anwendungen sind kaum Grenzen gesetzt.

Über Dienste wie https://icanhazip.com/ kann man sich seine öffentliche IP-Adresse, die zum Abrufen der Seite verwendet wurde, einfach anzeigen lassen und auch in Skripten verwenden. Möchte man die Aktualisierungen wirklich nur dann ausführen, wenn sich die IP geändert hat, so kann das Skript react_to_ip_change.sh helfen. Zu finden ist es im GIT.

Im wesentlichen Skript vergleicht das Skript eine gespeicherte IP mit der aktuell von https://icanhazip.com/ zurück gelieferten. Unterscheiden die beiden sich, so werden alle Skripte in /usr/local/etc/ipchange.d/ ausgeführt.

Kombiniert man das mit Cron, so aktualisiert man die eigene IP zeitnah in allen relevanten Systemen:

# m h dom mon dow command
* * * * * /usr/local/bin/react_to_ip_change.sh

Noch mal der Link zum GIT: https://code.nerd2nerd.org/n0ob/react_to_ip_changes