Werbung in eigener Sache: Werbung Werbung Werbung

PDFtk – PDF-Seiten ausschneiden, rotieren und mehr in der Konsole

PDFtk Logo mit decker software solutions Logo

Als ich neulich vor dem Problem stand nur eine Seite aus einer PDF in einer separaten PDF zu speichern, habe ich einen PDF-Drucker verwendet, der jedoch Hoch- und Querformat nicht passend konfigurieren kann. Ein paar Tage später stand ich dann vor dem Problem aus einer passwortgeschützen PDF eine ungeschützte PDF zu machen und bin nach kurzer Recherche auf das Tool PDFtk gestoßen, welches mein Passwort-Problem aber auch mein PDF-Drucker-Problem löste.

PDFtk steht für PDF Toolkit und bietet eine Vielzahl an Möglichkeiten, die gut dokumentiert sind. Das Tool ist sowohl für Linux als auch Windows verfügbar. Unter Debian könnt ihr PDFtk wie folgt installieren.

sudo apt update
sudo apt install pdftk -y

Für die einfache Entfernung eines Passworts könnt ihr einfach in der Konsole folgenden Befehl eingeben. Dazu müsst ihr nur secured.pdf durch den Pfad zur passwortgeschützen PDF ersetzen und foopass durch das Passwort. Als Ergebnis erhaltet ihr im aktuellen Verzeichnis eine unsecured.pdf, die ungeschützt ist. Den Namen der Datei könnt ihr natürlich auch frei wählen.

pdftk secured.pdf input_pw foopass output unsecured.pdf 

Damit ihr aus einer mehrseitigen PDF nur eine Seite oder eine bestimmte Auswahl in einer separaten PDF abspeichern könnt, hilft euch folgender Befehl. Dieser extrahiert aus der in.pdf-Datei die dritte Seite in die out1.pdf-Datei. Auch hier könnt ihr wieder Eingabe- und Ausgabe-Dateiname natürlich selbst wählen. Anstelle der Seite 3 könnt ihr auch Ausdrücke wie 3 5 8, um nur die Seite 3, 5 und 8 in der Ausgabe-Datei zu erhalten oder 1-endodd, wenn ihr alle ungeraden (odd) Seiten haben möchtet beziehungsweise 1-endeven alle geraden (even). Ein Blick in die Dokumentation lohnt sich hier auf alle Fälle, da auch noch mit Befehlen wie 1-4east eine Rotation der ersten vier Seiten um 90° möglich ist und vieles mehr.

pdftk in.pdf cat 3 output out1.pdf

Dies war nur ein kleiner Überblick über die Funktionalität von PDFtk. Wie bereits erwähnt, könnt ihr in der Dokumentation noch weitere Befehle finden. Dort ist erläutert, wie ihr Wasserzeichen eurer PDF hinzufügt, wie ihr Meta-Daten der PDF ändert und vieles mehr. Ich hoffe ihr könnt mit dem Tool auch etwas anfangen. Wenn ihr Fragen oder Anregungen habt, dann könnt ihr mich jederzeit gerne kontaktieren. Wenn ihr auch ein cooles Tool gefunden habt, dann schickt mir doch einen Link und vielleicht stelle ich es in einem nächsten Beitrag vor.

Warum wir alle Open-Source benutzen sollten

Tux mit decker-software-solutions Logo

Lange bin ich nicht mehr dazu gekommen, einen Blog-Eintrag zu schreiben und umso wichtiger ist es mir jetzt, mich mal wieder zu melden. Im Umgang mit Linux und vielen Open-Source Projekten in den letzten Jahren habe ich den Gedanken hinter Open-Source lieben gelernt. Nicht nur die Möglichkeit in den Quellcode hineinschauen zu können reizt mich dabei, sondern auch die Vertriebsmodelle dahinter. Umso mehr ich mich damit beschäftigt habe und mitbekomme, wie in Unternehmen und im öffentlichen Bereich gearbeitet wird, bin ich verwundert über die Herangehensweise. Es wird dabei in den meisten Fällen auf ein proprietäres Betriebssystem Windows gesetzt, also mit nicht einsehbarem Quellcode. Und darauf werden dann proprietäre Applikationen verwendet, sowie plattformabhängig Applikationen entwickelt, die nur unter Windows lauffähig sind.

Für mich macht das im öffentlichen Bereich aus mehreren Gründen keinen Sinn, die sich in soziale und ökonomische unterteilen lassen. Aus sozialer Sicht ist es nur sinnvoll auf freie Software zu setzen, da sich viele Familien keine kostenpflichtigen Applikationen leisten können. Wird jedoch in der Schule auf Microsoft Office gesetzt, haben die Schüler ohne Microsoft Office Nachteile. Sie müssen mit der Kompatibilität von alternativen Office Anwendungen kämpfen und müssen sich zusätzlich noch vor der Klassengemeinschaft bloß stellen, weil sie oder ihre Eltern sich die Software nicht leisten können. Besser wäre doch eine Schule, die vorgibt, dass die Schüler mit OpenOffice oder LibreOffice arbeiten müssen. Dadurch bekommen die Schüler keine Kompatibilitätsprobleme und werden nicht bloß gestellt. Zusätzlich sparen die Schulen noch Geld, beziehungsweise könnten die Lizenzkosten in die Weiterentwicklung der erwähnten Applikationen spenden und somit das gesamten Bildungssystem und deren Anwender unterstützen und nicht das Geld in die Taschen von Microsoft spielen. Oft wird als Gegenargument gebracht, dass Schüler auf das Leben vorbereitet werden sollen und dort oft die Produkte von Microsoft eingesetzt werden, doch wie will man ein Umdenken erreichen, wenn der nächsten Generation nur die proprietäre Lösung präsentiert wird. Tatsächlich wissen viele Schüler gar nicht, dass neben Windows noch andere Betriebssysteme existieren. Weiterhin muss auch gesehen werden, dass die Bedienkonzepte von Microsoft Office und LibreOffice oder OpenOffice sich kaum unterscheiden.

Aus ökonomischer Sicht kann der Einsatz und die Entwicklung von Open-Source Produkten einen deutlichen Mehrwert für den öffentlichen Bereich bringen. Offene Software verwendet offene Schnittstellen, die die Zusammenarbeit von mehreren Schulen, Kommunen, Gerichten und so weiter verbessern kann. Informationsaustausch wird dadurch verbessert und kostet nichts.

Offene Software lässt sich vom Zuständigen überprüfen, womit sichergestellt werden kann, dass keine Informationen an Dritte gesendet werden. Jedes Windows Betriebssystem sendet mittlerweile Daten über das Nutzerverhalten der Anwender an Microsoft. Doch soll Microsoft wirklich über das Nutzerverhalten von Schulkindern, oder Polizisten und uns selbst Bescheid wissen? Die Daten gehen zwar in der großen Datenflut unter, jedoch möchte ich persönlich trotzdem nicht, auch nicht anonymisiert, mein Nutzerverhalten teilen. Nicht weil ich etwas zu verbergen haben, sondern weil es mein einfaches Recht ist.

Der größte Punkt, der für den Einsatz von Open-Source Software im öffentlichen Bereich spricht, ist der Ursprung der Finanzierung. Letztlich bezahlt der Steuerzahler den Einsatz von kostenpflichtiger proprietärer Software im öffentlichen Bereich, wovon sich momentan nur die großen Firmen bereichern. Der Steuerzahler hat allerdings nichts davon. Würde das Geld für diese Software nach dem Gedanken Public Money, Public Code der Free Software Foundation Europe ausgegeben werden, könnte sicher fast jeder Steuerzahler davon profitieren. Wenn Office Applikationen ihren Funktionsumfang verbessern, haben alle was davon. Wenn Kommunen Software nutzen oder entwickeln lassen für beispielsweise ein Dokumentenmanagement, kann sicher das ein oder andere Unternehmen auch damit arbeiten und vorallem andere Kommunen, da die Anforderungen ähnlich, wenn nicht sogar identisch sind. Durch die Nutzung von Open-Source Produkten könnte schließlich eine sozialere Gesellschaft entstehen.

Mit Mailtrain Newsletter verwalten und steuern

mailtrain Für viele scheinen Newsletter eine veraltete Weise zu sein potentielle Kunden und Interessenten zu erreichen. Dennoch ist es sehr einfach damit Menschen zu erreichen und über HTML lassen sich auch ansprechende Newsletter erstellen, die alles andere als veraltet oder altmodisch sind. Ich wollte auch für euch die Möglichkeit schaffen, dass ihr eine Mail erhaltet, wenn ein neuer Beitrag online geht. Ich habe dann etwas auf GitHub herumgestöbert und bin schließlich mit Mailtrain fündig geworden. Wenn ihr wollt, könnt ihr euch direkt über diesen Link zum Newsletter anmelden. Mailtrain ist ein Applikation zum Erstellen, Verwalten und Konfigurieren von Newslettern. Laut Angaben der Seite können damit um die 500.000 Newsletter am Tag versendet werden, womit wohl die meisten Personen eine Weile beschäftigt sind, um so viele Abonennten zu erhalten.

Die Installation und Konfiguration von Mailtrain war nicht ganz so einfach und daher möchte ich euch hier eine Anleitung geben. Ich installiere das System auf einem Ubuntu Server 16.04 LTS. Möchtet ihr die Installation auf einem anderen System durchführen, müsst ihr bestimmte Links an euer System anpassen. Achtung: Auf der GitHub-Seite wird zwar auf install.sh-Skript verwiesen, das die Installation erleichtern soll, ich würde davon jedoch abraten, da mir persönlich damit 4 Stunden Wiederherstellungsarbeit bereitet wurden. Besser ist es die einzelnen Schritte zu verstehen. Zunächst bringen wir das System auf den aktuellen Stand und installieren alle Abhängigkeiten, die keine extra Aufmerksamkeit benötigen sollten (git, g++, imagemagick, redis). Weiterhin solltet ihr überprüfen ob euer Server folgende Ports nicht schon belegt hat und gegebenfalls diese in der folgenden Anleitung anpassen: 2525, 3000, 12080, 12081.

sudo apt update
sudo apt upgrade -y
sudo apt install git g++ imagemagick redis-server build-essential -y

Sowohl Mailtrain als auch eine weitere Applikation die Mailtrain zum Versenden von Nachrichten verwendet ZoneMTA, benötigen Node.js. Da vor kurzer Zeit die Version 8 den LTS (Long Term Support) erreicht hat, empfehle ich diese Version zu installieren. Am besten ihr installiert allgemein, wenn möglich, immer über den Paket Manager, da dieser euch automatisch mit Updates versorgt.

# add source destination and update via a script from nodejs
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
# install nodejs
sudo apt install -y nodejs

Kümmern wir uns zuerst um die Installation von ZoneMTA. Diese hat als weitere Abhängigkeit die MongoDB-Datenbank, die wir im Folgenden in der aktuellen Version 3.6 installieren.

# import public key
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 2930ADAE8CAF5059EE73BB4B58712A2291FA4AD5
# create a list file for mongodb
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.6 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.6.list
# update package managment database
sudo apt update
# install mongodb
sudo apt install mongodb-org -y

Anschließend erstellen wir für zone-mta einen eigenen Benutzer, geben diesem ein Passwort und erstellen für diesen ein Verzeichnis, indem wir ZoneMTA installieren können. Weiterhin laden wir direkt die Sourcen von GitHub in das entsprechende Verzeichnis.

sudo useradd -m zone-mta
sudo passwd zone-mta
# enter a password for zone-mta user
# create directory
sudo mkdir /opt/zone-mta
sudo chown zone-mta:zone-mta /opt/zone-mta
# login as zone-mta
su zone-mta
# switch to directory
cd /opt/zone-mta
# download sources
git clone https://github.com/zone-eu/zone-mta.git .

Nun erstellen wir die Konfigurationsdatei, installieren ZoneMTA und starten es schließlich.

cat >> config/production.json <<EOT
{
    "name": "Mailtrain",
    "user": "zone-mta",
    "group": "zone-mta",
    "queue": {
        "db": "/var/data/zone-mta/mailtrain"
    },
    "smtpInterfaces": {
        "feeder": {
            "enabled": true,
            "port": 2525,
            "processes": 2,
            "authentication": false
        }
    },
    "log": {
        "level": "info",
        "syslog": true
    },
    "plugins": {
        "core/email-bounce": false,
        "core/http-bounce": {
            "enabled": "main",
            "url": "http://localhost/webhooks/zone-mta"
        },
        "core/default-headers": {
            "enabled": ["receiver", "main", "sender"],
            "futureDate": false,
            "xOriginatingIP": false
        },
        "core/http-config": {
            "enabled": false,
        },
        "core/rcpt-mx": false
    },
    "pools": {
        "default": [{
            "address": "0.0.0.0",
            "name": "$HOSTNAME"
        }]
    },
    "zones": {
        "default": {
            "processes": 3,
            "connections": 5,
            "throttling": false,
            "pool": "default"
        },
        "transactional": {
            "processes": 1,
            "connections": 1,
            "pool": "default"
        }
    },
    "domainConfig": {
        "default": {
            "maxConnections": 4
        }
    }
}
EOT

npm install --production
npm start

Startet ZoneMTA ohne Fehler, können wir es mit Strg + C beenden und schließlich dem Autostart hinzufügen. Dazu wechseln wir zu einem Benutzer mit Adminrechten zurück, kopieren das Autostart-Skript, aktivieren es und starten es, damit wir nicht erst nach einem Neustart ZoneMTA gestartet haben.

# return to admin user
exit
# copy autostart skript
sudo cp /opt/zone-mta/setup/zone-mta.service /etc/systemd/system/
# enable service
sudo systemctl enable zone-mta.service
# start service
sudo systemctl start zone-mta.service

Nachdem wir ZoneMTA installiert haben, kümmern wir uns jetzt um die Konfiguration und Installation von Mailtrain. Zunächst benötigen wir einen MariaDB-Server, wenn nicht schon vorhanden und dort ein Datenbank und Datenbankbenutzer für Mailtrain. Das Passwort solltet ihr natürlich ändern. Hier solltet ihr im nachhinein dann auch noch dem root-Benutzer ebenfalls ein Passwort verpassen, damit kein Unbefugter in eurer Datenbank manipulieren kann.

sudo apt install mariadb-server -y
mariadb
CREATE USER 'mailtrain'@'localhost' IDENTIFIED BY 'secretpassword';
CREATE DATABASE mailtrain;
GRANT ALL PRIVILEGES ON mailtrain.* TO 'mailtrain'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;
exit

Jetzt erstelle wir, wie bereits für Zone-MTA, einen eigenen Benutzer, um dort die Dateien herunterzuladen und anschließend die Installation von Mailtrain vorzunehmen. Es hat bestimmte Vorteile für unterschiedliche Dienste unterschiedliche Benutzer anzulegen. So erhält man eine gute Trennung von Diensten und stellt auch sicher, dass bestimmte Dienste nur ihre Daten bearbeiten können und nicht andere.

sudo useradd -m mailtrain
sudo passwd mailtrain
# enter a password for mailtrain user
# create directory
sudo mkdir /opt/mailtrain
sudo chown mailtrain:mailtrain /opt/mailtrain
# login as mailtrain
su mailtrain
# switch to directory
cd /opt/mailtrain
# download sources
git clone https://github.com/Mailtrain-org/mailtrain.git .
# copy config file
cp config/default.toml config/production.toml
# open config file
nano config/production.toml

Es sollte nun die Konfigurationdatei geöffnet sein, in der ihr ein paar Anpassungen vornehmen müsst. Unter dem Abschnitt [mysql] müsst ihr das Passwort des mailtrain-Datenbanknuterz eingeben. Weiterhin könnt ihr unter [redis] enabled auf true setzten und unter dem Punkt [www] könnt ihr den Port von mailtrain anpassen, falls ihr Port 3000 bereits in Verwendung habt. Nachdem wir die Einstellungen geändert haben, können wir mit Strg + X, Y und Enter die Datei speichern und schließlich die Installation anstoßen, sowie Mailtrain zum ersten Mal starten.

npm install --production
NODE_ENV=production npm start

Hat das alles geklappt, könnt ihr nun unter http://localhost:3000 (sofern ihr die Portnummer nicht geändert habt) Mailtrain erreichen. Als erstes solltet ihr euch dann über Sign in mit Username admin und Passwort test anmelden und unter admin -> Account den Username und Passwort ändern. Dannach beenden wir mit Strg + C Mailtrain und fügen es, wie bereits ZoneMTA, dem Autostart hinzu.

# return to admin user
exit
# copy autostart skript
sudo cp /opt/mailtrain/setup/mailtrain.service /etc/systemd/system/
# enable service
sudo systemctl enable mailtrain.service
# start service
sudo systemctl start mailtrain.service

Jetzt solltet ihr unter admin -> Settings eure Einstellungen noch vornehmen. Hauptsächlich sollte dazu unter Mailer Settings, die Einstellungen Hostname auf localhost, Port auf 2525 und Encryption auf Do not encryption gesetzt werden. Damit solltet ihr Mailtrain für die ersten Tests installiert und konfiguriert haben und könnt nun selbst mit den Möglichkeiten herumspielen. Ich habe beispielsweise in der Navigationsleiste unter Lists eine eigene Liste angelegt, dort meine eigene Mailadresse hinzugefügt. Ich habe dann unter Templates einfach mal einen Standard-Newsletter erstellt und schließlich unter Campaigns einen leeren Newsletter an die Liste versendet, die nur meine Mailadresse enthält. Ihr könnt auch einen Testbenutzer anlegen, an den ihr den Newsletter versendet bevor alle Abonennten diesen erhalten. Weiterhin ist es auch möglich einen RSS-Feed als Newsletter anzubieten. Da mein Blog bereits einen RSS-Feed anbietet, habe ich jetzt einfach mal für euch eine Newsletter-Liste erstellt, die euch immer per Mail über neue Blog-Eintrage informiert. Dazu müsst ihr einfach euch unter folgendem Link Link anmelden. Wie immer hoffe ich jetzt, dass euch der Beitrag geholfen hat. Solltet ihr noch Fragen oder Anregungen haben, dann könnt ihr mich jederzeit gerne kontaktieren. Und wenn ihr euch einfach zum Newsletter anmeldet, bekommt ihr immer mit, was ich gerade so treibe. Was nicht zu vergessen ist, dass ihr die Datenbanken und Konfigurationsdateien eurem Backup hinzufügt, denn es gibt nichts ärgerliches, als wenn die mühsellige Arbeit einfach weg ist.

wikijs – Eigenes Wiki zum Austausch

wikijs Auf der Suche nach einer Möglichkeit Informationen nicht nur in einem Dokument zu speichern, sondern diese auch möglichst einfach zu teilen, bin ich vor ein paar Jahren bereits auf Mediawiki gestoßen. Mediawiki bietet eine solide Lösung zum Speichern und Teilen von Informationen. Es lassen sich so beispielsweise innerhalb eines Teams, einer Firma oder aber auch einer Familie Informationen austauschen ohne dafür ein Dokument öffnen zu müssen. Die Informationen lassen sich einfach im Browser abrufen, womit von jedem Endgerät auf diese Information zugegriffen werden kann. Nach meinem Empfinden hat mir Mediawiki allerdings nie so ganz gefallen und daher habe ich mich, vor allem mit dem Augenmerk auf eine Lösung mit nodejs, etwas umgeschaut. Fündig wurde ich bei wiki.js(aktuell in Version 1.0.12), was für mich die moderne Lösung von Mediawiki ist. Letztlich schreibt man die Beiträge auch in der Markdown-Sprache aber es bietet mir direkt eine moderne ansprechende Weboberfläche.

Damit ihr auch etwas davon habt, beschreibe ich euch gerne kurz die notwendigen Schritte zur Installation auf einem Ubuntu Server 16.04 LTS. Es sollte allerdings (fast) genauso auf einem Raspberry Pi oder ähnlichem Debian-System funktionieren. Zunächst müssen wir die notwendigen Vorraussetzungen erfüllen. Dazu müssen wir NodeJs, MongoDB und git installieren. Manches wird vielleicht bei euch schon installiert sein, allerdings werdet ihr gegebenfalls darauf hingewiesen.

Zunächst bringen wir das System auf einen aktuellen Stand und installieren im Anschluss NodeJs und git.

sudo apt update
sudo apt upgrade -y
# install long time support (LTS) version 8.x
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
sudo apt install nodejs -y
# install git
sudo apt install git -y

Zur Installation von MongoDB benötigen wir ein paar mehr Schritte. Zunächst wird das System so konfiguriert, dass es weiß, woher die MongoDB Quelldateien kommen und woher es auch Updates beim Systemupdate bekommt. Dazu erstellen wir die Datei /etc/apt/sources.list.d/mongodb-org-3.6.list. Hier wird beschrieben und festgelegt, für welches Betriebsystem die Daten geholt werden. Möchtet ihr wiki.js auf einem anderen System installieren, dann könnt ihr unter https://docs.mongodb.com/manual/administration/install-on-linux/ den entsprechenden Link in Erfahrung bringen.

sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 2930ADAE8CAF5059EE73BB4B58712A2291FA4AD5
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.6 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.6.list
# load informations from all files in sources.list
sudo apt update
# install mongodb
sudo apt install mongodb-org -y

Jetzt können wir die Datenbank-Software MongoDB starten und schließlich testen, ob sie wirklich gestartet ist. Hat alles geklappt, sollte nach Eingabe des letzten Befehls die Ausgabe ein Active: active (running) enthalten.

sudo systemctl start mongod.service
sudo systemctl status mongod.service

Nun können wir wiki.js installieren. Dazu erstellen wir ein Verzeichnis, worin wir es installiert wollen und führen ein Installations-Skript aus.

mkdir -p ~/wikijs
cd ~/wikijs
curl -sSo- https://wiki.js.org/install.sh | bash

Abschließend müsst ihr den Konfigurationsprozess starten und in euerem Browser auf die Seite http://localhost:3000 navigieren - beziehungsweise anstatt localhost die IP-Adresse eures Severs eingeben, wenn ihr euch nicht lokal befindet.

node wiki configure

Auf der Website könnt ihr dann einfach den Schritten zur Konfiguration folgen. Diese sind in der Regel selbsterklärend, jedoch ein paar kurze Anmerkungen: Unter dem Reiter General könnt ihr die URL angeben, unter die eurer Wiki erreichbar sein soll. Ich habe hier beispielsweise unter Host http://decker-server:3000 angegeben und bei Port 3000 (Da ich auf Port 80 meines lokalen Servers bereits einen anderen Dienst zur Verfügung stelle). Ihr könnt eure Einstellungen hier auch wie vorkonfiguriert lassen, wenn Port 80 bei euch nicht belegt ist. Ihr werdet auch noch nach dem MongoDB Connection String gefragt. Standardmäßig wird die Datenbank in mongodb://localhost:27017/wiki abgelegt. Möchtet ihr eure Datenbank anders benennen, dann müsst ihr die Adresse beispielsweise so ändern mongodb://localhost:27017/decker-wiki. Kurz vor Abschluss der Konfiguration werdet ihr noch nach einem Git Repository gefragt. Diesen Schritt könnt ihr zwar überspringen, damit werden eure Daten allerdings auch nicht gesichert und ihr müsst euch eine eigene Backup-Strategie überlegen. Ich hatte hier Probleme mein lokales Repository vom Gitlab-Server anzugeben und habe diesen Schritt daher übersprungen und nachträglich direkt in der Konfigurationsdatei gemacht. Dazu öffnen wir die Datei ~/wikijs/conig.yml mit nano.

nano ~/wikijs/conig.yml

Wir müssen jetzt den Eintrag git: false durch folgendes ersetzen. Wobei ihr diese selbstverständlich mit euren Daten füllen müsst.

git:
  url: git@decker-server:decker-software-solutions/decker-wiki.git
  branch: master
  auth:
    type: ssh
    privateKey: /home/chris/.ssh/id_rsa
    sslVerify: true
  signature:
    name: Christian Decker
    email: christian.decker@decker-software-solutions.de

Nach einem node wiki restart erreicht ihr schließlich euer Wiki unter der in der Konfiguration angegeben Adresse und könnt loslegen. Ich hoffe ich konnte euch helfen euer Wiki einzurichten. Und wie immer gilt: Solltet ihr Fragen oder Anregungen haben, dann könnt ihr mich jederzeit gerne kontaktieren. Ich freue mich auch immer über Feedback und Ideen für neue Blogeinträge.

gPhoto2 – FotoBox selbst gemacht mithilfe von Raspberry Pi

gphoto2 Bei Hochzeiten ist es mittlerweile fast schon Standard eine Fotobox zu haben, um unvergessliche Bilder zu sammeln. Leider sind diese oft teuer und/oder ausgebucht und wir haben uns die Frage gestellt, ob wir uns nicht selbst eine Fotobox basteln können. Die Antwort ist natürlich ja und wenn man die notwendigen Teile schon zu Hause hat, dann kostet das Ganze auch nur etwas Zeit. Benötigt wird ein Raspberry Pi (vermutlich geht es mit allen, ich würde jedoch einen Raspberry Pi 2 oder 3 nehmen), eine Kamera mit Selbstauslöser und ein Stativ für die Kamera. Wie im Bild zu sehen, haben wir noch einen Bildschirm angeschlossen, der das aktuell geschossene Bild zeigt. Wir wollen uns hier aber nur um die Aufnahme und nicht die Darstellung kümmern.

Um herauszufinden, ob eure Kamera mit der folgenen Installation und Konfiguration funktioniert, könnt ihr unter http://www.gphoto.org/doc/remote/ den Status überprüfen. Dort werden die von der gPhoto2 unterstützen Kameras aufgelistet und auch so manche mit denen es auch nicht geht. Ich hoffe euere Kamera ist dabei und wir können klassisch loslegen mit der Installation der benötigen Software. Dazu updaten wir erst einmal unsere Quellen und installieren vorhandene Pakete. Ich arbeite dafür, wie meistens, mit einem Raspbian Lite, da mir das möglichst viel Spielraum für eigene Daten lässt und keine unnötigen Dienste installiert.

# update and upgrade
sudo apt update
sudo apt upgrade -y
# install gPhoto2
sudo apt install gphoto2 -y

Jetzt fehlt nur noch ein Skript, das die Kamera erkennt und die Bilder direkt auf den Raspberry Pi lädt. Dazu legen wir zunächt eine Datei an, machen diese ausführbar und öffnen sie schließlich.

mkdir -p /home/pi/img
touch /home/pi/img/cameracapture.sh
chmod +x /home/pi/img/cameracapture.sh
nano /home/pi/img/cameracapture.sh

Im Skript selbst wird einfach in einer Dauerschleife nach einer Kamera gesucht. Wird diese mit dem gphoto2-Befehl gefunden, wird über den wait-event-and-download-Parameter festgelegt, dass die Bilder direkt von der Kamera geladen werden und über filename wird weiterhin dem aufgenommenen Bild ein Dateiname mit aktuellem Zeitstempel und Bildnummer gegeben. Ansonsten würde nach einem Neustart die Kamera wieder mit cap0001.jpg beginnen, womit bestehende Bilder zwar über den force-overwrite-Parameter überschrieben werden könnten, aber damit auch verloren sind. Mit diesem Aufruf werden alle Bilder gespeichert.

#!/bin/bash
while true
do
        echo 'search camera'
        gphoto2 --wait-event-and-download --filename "%Y_%m_%d_%H_%M_%S_%n.jpg"
        sleep 1
done

Das Skript kann dann mit Strg+X und Enter gespeichert werden und schließlich wie folgt ausgeführt werden. Ist eure Kamera noch nicht angeschlossen wird jetzt durch sleep 1 jede Sekunde nach einer angeschlossenen Kamera gesucht. Der sleep ist notwendig, da das Skript sonst enorm viele Resourcen von dem Raspberry Pi benötigt, wenn er ununterbrochen nach einer Kamera sucht.

/bin/bash /home/pi/img/cameracapture.sh

Ich hoffe ich konnte euch auf dem Weg zu eurer eigenen FotoBox helfen. Solltet ihr Interesse an einer etwas anderen FotoBox haben, dann können wir auch unsere EveBox empfehlen. Solltet ihr Fragen oder Anregungen haben, dann könnt ihr mich jederzeit gerne kontaktieren.

GitLab – Continous Integration-Server mit Docker für Tests

gitlabdocker Zum Entwickeln eigener Projekte habe ich zu Hause einen eigenen GitLab-Server installiert, den ich seit geraumer Zeit auch für Unit-Tests und Lint verwende. GitLab bietet dazu über einen Continous Integration-Server (kurz CI-Server), die Möglichkeit beim Einchecken von neuem Code automatisch die Tests ablaufen zu lassen und dem Entwickler bei Misserfolg über eine Mail in Kenntnis zu setzen. Zur Konfiguration des CI-Servers gibt es mehrere Möglichkeiten. Zum Einen kann der Code direkt auf dem Host des Servers ausgeführt werden. Das hat jedoch den Nachteil, dass ich bei bestimmten Entwicklungsumgebungen extrem aufpassen muss, dass diese mir nicht Probleme auf dem Server machen. Beispielsweise, wenn ich in Python bestimmte Bibliotheken in einer bestimmten Version benötige, diese jedoch von einem Programm auf dem Server in einer anderen Version gebraucht werden. Zum Anderen habe ich aber auch die Möglichkeit den Code in einem Docker-Container auszuführen. Dies hat mehrere Vorteile. Die angesprochene Problematk wird gelöst, da alle Entwicklungsumgebungen in einem separaten Container gestartet werden, was den Host nicht verändert und es lassen sich damit unterschiedliche Versionen testen. Soll die Software beispielsweise mit Nodejs 6.11.3 und 8.5.0 kompatibel sein, lässt sich beides testen, indem unterschiedliche Docker-Images zum Einsatz kommen.

Für die Konfiguration von GitLab mit Docker müssen wir zunächst einmal Docker installieren. Leider werden nicht immer die aktuellen stabilen Versionen von bestimmen Paketen mitgeliefert. Daher deinstallieren wir erstmal Docker, falls dies bereits vorhanden ist und fügen dann die aktuellen stabilen Quellen hinzu, bevor wir es letztlich installieren. Ich installiere das Ganze auf einem Ubunutu Server 16.04.3 LTS.

# remove old docker installation
sudo apt remove docker docker-engine docker.io
# add current stable docker sources
sudo apt update
sudo apt install -y apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
# update sources
sudo apt update
# install community edition from docker
sudo apt-get install docker-ce
# upload and start docker container hello-world
sudo docker run hello-world

Nach dem letzten Befehl sudo docker run hello-world solltet ihr eine Ausgabe bekommen, die mit Hello from Docker beginnt, womit ihr die Installation von Docker erfolgreich abgeschlossen habt. Jetzt müssen wir den GitLab-Runner installieren und entsprechend mit Docker einen GitLab-Runner konfigurieren. Zur Installation des GitLab-Runner genügt folgender Befehl:

sudo apt install -y gitlab-ci-multi-runner

Für die Konfiguration benötigen wir jetzt noch ein paar individuelle Informationen eures GitLab-Servers. Dazu meldet ihr euch als Admin auf eurem GitLab-Server an und wechselt in der Admin-Area auf den Reiter Runners (sollte <GitLab-Server>/admin/runners sein). Dort findet ihr unter How to setup a shared Runner for a new project die Informationen, welche URL (<GitLab-Server>) und Token (<Token>) ihr im Folgdendne angeben müsst. Dazu einfach im folgenden Befehl die Platzhalter ersetzen und letztlich alles mit Enter quittieren.

sudo gitlab-runner register --url "<GitLab-Server>" --registration-token "<Token>" --description "docker" --executor "docker" --docker-image node:6.11.3

Dadurch haben wir jetzt einen GitLab-Runner konfiguriert, der als Standard-Image ein Nodejs-Server in Version 6.11.3 verwendet. Die Angabe des Docker-Images lässt sich aber in jeder gitlab-ci-Datei seperat definieren. Aktualisiert ihr jetzt die geöffnete GitLab-Seite (<GitLab-Server>/admin/runners), sollte dort ein neuer Runner-Eintrag vorhanden sein.

Möchtet ihr jetzt beispielsweise eure Nodejs-Applikation in Version 6.11.3 und 8.5.0 testen, so könnt ihr eurem Projekt die Datei .gitlab-ci.yml hinzufügen und folgenden Inhalt hinzufügen. Dadurch werden beide Versionen getestet.

node_6:
  image: node:6.11.3
  script:
   - npm install
   - npm run test

node_8:
  image: node:8.5.0
  script:
   - npm install
   - npm run test

Mit dieser Konfiguration laufen eurere Tests jetzt in einem vom Server-System abgekapselten Docker-Images, womit ihr die auf dem Server installierten Pakete unangetastet lassen könnt. Weiterhin könnt ihr jetzt mit unterschiedlichen Docker-Images euere Tests laufen lassen und somit besser eure Software testen. Ich hoffe der Beitrag hilft euch bei der Konfiguration und verbessert eueren Alltag. Solltet ihr Fragen oder Anregungen haben, dann könnt ihr mich jederzeit gerne kontaktieren.

LinConnect – Android-Benachrichtigungen am Computer erhalten

fhem Oft, wenn ich am Rechner sitze, verpasse ich immer Anrufe auf meinem Android-Smartphone, da dies lautlos und ohne Vibration in der Hosentasche ist. Mein Wunsch war also, dass ich die Benachrichtigungen über eingehende Anrufe im Benachrichtungsdienst meines Ubuntu-Rechners erhalte. Die Lösung nennt sich LinConnect. Das System besteht aus einer Server-Applikation auf dem Linux-Desktop (muss nicht Ubuntu sein) und einer Android-App, die als Client auf dem Smartphone läuft.

Zur Installation haben die Entwickler ein Installations-Skript angelegt. Doch bevor dies ausgeführt werden kann, müssen die Abhängigkeiten installiert werden. Dazu die folgenden Befehle in der Konsole ausführen.

sudo apt install -y python-pip python-gobject git libavahi-compat-libdnssd1 gir1.2-notify-0.7
wget https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/pybonjour/pybonjour-1.1.1.tar.gz
tar zxf pybonjour-1.1.1.tar.gz
cd pybonjour-1.1.1
sudo python setup.py install
cd ..
rm pybonjour-1.1.1.tar.gz
find pybonjour-1.1.1 -delete

Jetzt sind wir soweit, dass LinConnect installiert werden kann. Mit folgenden Befehlen ladet ihr das Installations-Skript herunter, macht dies ausführbar und startet es.

wget --quiet https://raw.github.com/hauckwill/linconnect-server/master/LinConnectServer/install.sh
chmod +x install.sh
./install.sh

LinConnect Screenshot Nach dem Start des Skript werden Fragen zur Installation gestellt, die ich unter Ubuntu (was auf Debian basiert) wie folgt beantwortet habe.

Install LinConnect server? [Y/N]Y
Install dependencies automatically (for Debian-based distros) [Y/N]Y
Autostart LinConnect server on boot? [Y/N]Y
Install complete. Start LinConnect server now? [Y/N]Y

Der LinConnect-Server sollte jetzt starten und auch immer nach dem Starten des Computers automatisch aktiv sein. Als Gegenstelle wird jetzt noch die LinConnect-App benötigt, die ihr im App-Store findet. Sind Smartphone und Rechner im gleichen Netzwerk, findet die App automatich den Server und sendet Benachrichtigungen an den eigenen Computer. So erhält man dann alle Benachrichtigungen, wie Anrufe, Messenger und sonstige Meldungen (siehe Bild). In der App lassen sich dann unter Configuration –> Enable applications auch Apps abwählen, die keine Benachrichtigungen senden sollen. Beispielsweise bekommt man sonst Benachrichtigungen von neuen Mails doppelt, da Thunderbird und die Mail-App auf dem Android-Smartphone eine Benachrichtigungen schicken.

Ich hoffe ich konnte euch helfen. Solltet ihr Probleme bei der Installation oder Konfiguration haben, dann könnt ihr mich gerne kontaktieren. Ich freue mich immer über eure Mails.

FHEM – Einrichten von Heizungsthermostaten mit Raspberry Pi

fhem Wie bereits in einem älteren Blog-Eintrag beschrieben, verwende ich zu Hause FHEM mit dem HM-MOD-RPI-PCB-Modul von ELV auf einem Raspberry Pi 2. In dem Blog-Eintrag ist auch beschrieben, wie FHEM mit dem Modul auf dem Raspberry Pi installiert werden kann. Damals wollte ich einfach das Smarthome-System auf dem Raspberry Pi testen und hatte daher auch nur einen Außentemperatursensor bestellt. Da wir in eine neue Wohnung gezogen sind und hier die Heizungsthermostate nicht wie in der alten ein eigenes System haben, hab ich beschlossen mir von Homematic die passenden Heizungsthermostate HM-CC-RT-DN zu bestellen. Diese haben den Vorteil, dass sie selbst die Raumtemperatur messen können und daher keinen zusätzlichen Temperatursensor im Raum benötigen.

Mein Ziel ist es durch das System Heizkosten zu sparen, indem sich Wochenpläne definieren lassen, die es ermöglichen die einzelnen Zimmer in der Wohnung zu bestimmten Tagen und zu bestimmten Uhrzeiten zu heizen, beziehungsweise nicht zu heizen. In der Verpackung der Heizungsthermostate sind notwendige Adapter für die gängigsten Heizungsventile vorhanden und auch eine Montageanleitung, die ich euch ans Herz legen würde, damit der Thermostat richtig an der Heizung sitzt. Die weitere Einrichtung in FHEM möchte ich jetzt im Folgenden erklären.

Die Installation der Thermostate bezieht sich auf die Einstellungen, die bereits in diesem Blog-Eintrag gemacht wurden. Solltet ihr hier von abgewichen sein, müsst ihr dies selbstverständlich beachten. Wir öffnen als erstes unsere FHEM-Seite unter http://raspberry:8083/fhem. Damit wir unsere Thermostate nun mit dem Modul pairen können, müssen wir das Modul öffnen. Dazu fügt ihr folgenden Befehl oben ein und drückt Enter.

set myHmUART hmPairForSec

Als nächstes möchten wir jetzt den Thermostat verbinden und drücken dazu auf dem Thermostat für 3 Sekunden auf die mittlere Taste (Boost-Taste). Es beginnt ein Countdown von 30 herunterzuzählen. War die Verbindung erfolgreich, erscheint ein AC auf dem Thermostat-Display. Weiterhin solltet ihr jetzt unter http://raspberry:8083/fhem?room=all weitere Einträge unter CUL_HM finden. Hat die Verbindung nicht funktioniert, solltet ihr versuchen den Raspberry Pi zum Anlernen möglichst in die Nähe des Thermostates bringen. Danach könnt ihr ihn wieder an den gewohnten Platz stellen (Das hat zumindest bei mir dann sofort funktioniert).

Damit wir erstmal keine anderen Geräte anlernen, ist es sinnvoll das Modul wieder zu schließen. Das hat auch den Vorteil, dass ich Thermostat für Thermostat anlernen kann und den richtigen Zimmern zuordnen kann, bevor ich alle Thermostate in FHEM habe und mir erstmal schwer fällt über die kryptische Nummer herauszufinden, wo der zugehörige Thermostat installiert ist. Also folgenden Befehl wieder einfügen und Enter drücken.

set myHmUART close

weekprofile FHEM Jetzt möchten wir als die Konfiguration des Thermostats in FHEM laden. Dazu nehmen wir die unter http://raspberry:8083/fhem?room=all erschienenen Einträge zur Hilfe. In meinem Fall stehen hier jetzt unter CUL_HM: HM_5ABEDF_Clima, HM_5ABEDF_ClimaTeam, HM_5ABEDF_Climate und so weiter. Zum Laden der Konfiguration benötigen wir allerdings nur die kryptische Nummer HM_5ABEDF und können dann mit folgendem Befehl die Konfiguration laden. In eurem Fall müsst ihr natürlich die Nummer durch eure ersetzen.

set HM_5ABEDF getConfig

Nach Ausführung des Befehls werden die Einträge von HM_5ABEDF_Clima, HM_5ABEDF_ClimaTeam, HM_5ABEDF_Climate und so weiter mit den erhaltenen Informationen befüllt. Hier könnt ihr jetzt auch beispielsweise schon mit dem Dropdown-Menü bei HM_5ABEDF_Clima die gewünschte Temperatur festlegen. Ihr könnte auch diese Zeile direkt einem Zimmer zuordnen, indem ihr folgenden Befehl ausführt.

attr HM_5ABEDF_Clima room Wohnzimmer

Zum Anlegen des angesprochen Wochenplans könnt ihr mit folgendem Befehl eine grafische Komponente in FHEM dafür erhalten. Dort lassen sich dann mehrere Profile erstellen, wo ihr genau definieren könnt, wie geheizt werden soll. Über den –>-Button lässt sich dann das Profil auf den Thermostat übertragen.

define Heizungsplan weekprofile HM_5ABEDF_Clima

Ich hoffe ich konnte euch beim Einrichten der Thermostate in FHEM helfen. Ich bin zufrieden mit dem System, weil ich mit dem Raspberry Pi neben der Hausautomatisierung auch andere Probleme lösen kann und werde vermutlich auf diesem Raspberry Pi auch die Software für den MagicMirror installieren. Solltet ihr Probleme haben oder Fragen, dann könnt ihr mich gerne kontaktieren. Ich versuche dann so gut es geht zu helfen.

Radicale – Kalender und Kontakte auf dem eigenen Server (Raspberry Pi) verwalten

Radicale Decker

Ich verwendete schon seit Jahren Baikal zum Speichern meiner Kalender-Einträge und Kontakte. Früher noch auf meinem Raspberry Pi mittlerweile auf meinem Heim-Server. Ich bin völlig zufrieden mit der Lösung und war daher traurig darüber, dass das Projekt nicht mehr weiter entwickelt wird http://sabre.io/blog/2017/development-on-hold/. Aktuell läuft noch alles perfekt, doch war ich dennoch auf der Suche nach einer Alternative und bin auch fündig geworden. Radicale ist ein in Python3 implementierter CalDAV- und CardDAV-Server, der mir die gleichen Vorzüge wie Baikal bietet und ist ebenso schlank implementiert, dass es auch ohne Probleme auf dem Raspberry Pi läuft.

Die Installation ist denkbar einfach. Ihr solltet zunächst python3 und pip installieren und anschließend radicale.

# install python3 and pip
sudo apt install python3 python3-pip -y
# install radicale
sudo python3 -m pip install --upgrade radicale

Nach diesen Schritten legt ihr eine Konfigurationsdatei an, mit der ihr festlegt, dass ihr den Server auch innerhalb eures Netzwerkes erreicht, da standardmäßig nur ein lokaler Zugriff gestattet wird.

sudo mkdir -p /etc/radicale
sudo nano /etc/radicale/config

Fügt folgende Zeilen ein und speichert mit Strg+X und Y und Enter.

[server]
hosts = 0.0.0.0:5232

Jetzt können wir radicale zum ersten Mal starten, wobei ihr über den storage-filesystem-folder angeben könnt, wo eure Daten gespeichert werden und damit auch welchen Ordner ihr im Anschluss von diesem Blog-Eintrag eurem Backup hinzufügen müsst.

python3 -m radicale --storage-filesystem-folder=/home/pi/radicale/collections

Jetzt könnt ihr unter http://localhost:5253, wenn ihr euch direkt auf dem Server befindet, oder aber auch http://raspberrypi:5253 aufrufen, wenn ihr euch in eurem Netzwerk befindet. Es zeigt sich jetzt eine Weboberfläche, die seit Version 2.1 in radicale integriert ist und mit der ihr ganz einfach neue Nutzer anlegen könnt und neue Kalender und Todo-Listen oder Adressbücher erstellt. Meldet euch dazu einfach mit eurem gewünschten Nutzernamen und Passwort an. Der Nutzer wird automatisch generiert. Am Besten ihr speichert direkt euer Passwort, weil ich noch keine Möglichkeit gesehen habe, das Passwort zurück zusetzen oder eine Datei zu finden, wo das Passwort im Klartext steht. Dann klickt ihr einfach auf Create new addressbook or calender, legt Title, Description, Type und Color fest und bestätigt mit Create euren Vorgang. Zur Belohnung bekommt ihr einen URL-Link, mit dem ihr jetzt Zugriff auf den Kalender und Todo-Liste oder Adressbuch erhalten könnt.

Die erhaltene URL könnt ihr beispielsweise in Thunderbird beim Erstellen eines neuen Kalenders angeben. Dazu beim Anlegen eines Kalender Im Netzwerk auswählen und dann CalDAV auswählen, sowie die URL in den vorgesehenen Bereich kopieren. Nach Weiter, Festlegung des Namens und der Farbe, Weiter und Fertigstellen könnt ihr dann den Kalender in Thunderbird verwenden, sobald ihr euren Benutzername und Passwort von radicale eingegeben habt. Für die Verwendung am Smartphone empfehle ich die DAVDroid-App. Dort könnt ihr auch, wenn ihr nur den Anfang eurer URL, in meinem Fall http://raspberrypi:5232/christian.decker, eintragt mehrere Adressbücher und Kalender laden.

Damit der Server automatisch gestartet wird, müssen wir jetzt noch ein Autostart-Skript erstellen. Dazu erstmal über Strg+C die Ausführung des aktuellen Skriptes beenden und anschließend erstellen wir die Datei radicale.service.

sudo nano /etc/systemd/system/radicale.service

Fügen folgenden Inhalt hinzu und speichern mit Strg+X und Y und Enter.

[Unit]
Description=A simple CalDAV (calendar) and CardDAV (contact) server

[Service]
ExecStart=/usr/bin/env python3 -m radicale --storage-filesystem-folder=/home/pi/radicale/collections
Restart=on-failure

[Install]
WantedBy=default.target

Jetzt können wir das Skript aktivieren, starten und direkt den Status überprüfen. Hier solltet ihr jetzt ein active (running) finden und ihr solltet

# enable service
sudo systemctl enable radicale.service
# start service
sudo systemctl start radicale.service 
# check status
sudo systemctl status radicale.service 

Nach einem Reboot (_sudo reboot) sollte radicale jetzt automatisch starten. Die Kommunikation zwischen eurem Smartphone oder Computer ist jedoch noch unverschlüsselt und ihr solltet entweder dafür sorgen, dass euer Server wirklich nicht von außen erreichbar ist oder ihn über einen Reverse Proxy mit nginx und einem Zertifikat absichern, wie hier beschrieben.

Ich hoffe, ich konnte euch einen guten Einblick in die Installation und Konfiguration von radicale bieten. Solltet ihr noch weitere Fragen haben, dann könnt ihr mich gerne kontaktieren.

EveBox – Interaktives Gruppenerlebnis auf Hochzeiten, Geburtstagen und sonstigen Events

EveBox Wir sind stolz, dass wir heute eine kleine Veröffentlichung feiern können. Im Zuge unserer Hochzeit haben wir ein Spiel für unsere Gäste entwickelt, das wir gerne mit euch teilen würden. EveBox ist ein interaktives Spiel, das es euch als Gastgeber ermöglicht euren Gästen Aufgaben zu stellen, die dann mit Smartphone oder aufgebauten Laptop-Stationen erledigt werden können. Es soll sich dabei ideal in euer Fest integrieren.

Das Spielprinzip ist denkbar einfach. Jeder Gast kann eine bestimmte Anzahl an Aufgaben lösen und bekommt dafür Punkte. Alle Gäste spielen zusammen und sammeln somit Punkte, um im Voraus ausgesuchte Bilder der Gastgeber freizuspielen. Zum Spielen gibt es vier Aufgabentypen: Aufgabe, Bild, Video und Frage. Aufgaben können dann beispielsweise “Tanze mit der Mutter des Bräutigams”, “Gib einem fremden ein Kompliment”, “Fotografiere eine Grimasse” und “Mache ein Foto von dir im Häschen-Kostüm” sein. Der Kreativität der Gastgeber sind dabei jedoch keine Grenzen gesetzt. Die freigespielten Bilder der Gastgeber sowie die eingereichten Aufgaben der Gäste mit Typ Bild werden dann während des Festes in einer Bilderschau auf einem Display dargestellt.

Aus eigener Erfahrung wurde das Spiel sehr gut angenommen und führt vor allem bei gemischten Gesellschaften wie bei Hochzeiten, wo sich die Gäste teilweise zum ersten Mal sehen, durch Aufgaben mit “Fremden” zum besseren gegenseitigen Kennelernen. Weiterhin entstehen viele lustige Bilder, Videos und Textbeiträge, die für die Gastgeber und Gäste für immer in Erinnerung bleiben werden. Im Zeitalter von Digitalisierung und Smartphone gehört unseres Erachtens nach EveBox zu einem unvergesslichen Event dazu. Wenn ihr herausfinden wollt, was EveBox genau ist, dann könnt ihr einfach auf die Homepage https://evebox.de gehen. Habt ihr noch Fragen oder wollt EveBox auf eurem nächsten Event ausprobieren? Dann findet ihr dort auch Kontaktmöglichkeiten.

subscribe via RSS