Schlagwort-Archive: Tutorial

IFTTT oder: Wie man Instagram-Fotos ordentlich zu Twitter schickt

Wer Instagram und Twitter nutzt kennt das Problem: Man möchste seine Instagram-Kreation natürlich direkt auch auf den eigenen Twitter-Kanal schicken und macht das so:

Leider ist das Instagram-Bild auf Twitter dann nicht zu sehen, es wird nur verlinkt:

Der Grund: Instagram gehört seit 2012 zu Facebook, und Twitter und Facebook sind sich bekanntlich nicht so grün. Daher zickt Twitter und weigert sich, die Instagram-Bilder direkt in der Timeline anzuzeigen. Jedenfalls gilt das für die offizielle Twitter-App, den Stream auf der Webseite und auch für das zu Twitter gehörende  und von mir geschätzte Tweetdeck. Technisch wäre das Einbinden der Bilder vermutlich kein Problem, aber man ist eben Konkurenz.

Jetzt bin ich mal wieder gefragt worden, wie ich es hinbekomme, dass meine Instagram-Bilder doch als native Twitter-Bilder im Stream angezeigt werden:

Der Link im Screenshot verrät es schon: Ich nutzte IFTTT („if this then that“). Wenn du von diesem Dienst noch nichts gehört haben solltest wird es allerhöchste Zeit. Der Name des Dienstes sagt schon genau, was er macht:

Wenn irgend etwas passiert (der „Trigger“), dann mach irgend etwas anderes (die „Action“).

Und dieses „irgend“ ist in der Regel irgend ein Webdienst: Twitter, Facebook, Instagram, das Wetter, eine Uhrzeit, Dropbox, der Akkustand des Handys, eine SMS, Mail, eBay, Kalender, ein RSS-Feed, WordPress, Youtube, OneNote, Feedly, Pocket, Philips Hue, … Und diese Dienste kann man nun verknüpfen. Zur Veranschaulichung ein paar Beispiele:

  • Wenn mich jemand auf einem Facebook-Foto markiert, dann speichere dieses Foto in meine Dropbox.
  • Wenn ich in Feedly einen Artikel als „gespeichert“ markiere, dann speichere ihn in meiner Pocket-Leseliste.
  • Wenn ich eine SMS bekomme, dann speichere sie in einer Google Tabelle.
  • Wenn es 19 Uhr ist, dann schicke mir den Wetterbericht für morgen per Pushbullet auf’s Handy.
  • Wenn ich einen Blogpost bei WordPress veröffentliche, dann schicke mir eine Erinnerung auf’s Handy, dass ich den noch bei Facebook und Twitter poste (man könnte das auch direkt mit IFTTT schicken, wenn man das wollte).
  • Wenn es 23 Uhr ist, dann schalte mein Yeelight-Schreibtischlicht aus um mich daran zu erinnern, dass es langsam Zeit wird, ins Bett zu gehen.
  • Wenn ich eine Mail mit einem bestimmten Betreffe erhalte, dann speichere den Anhang in meine Dropbox.
  • Wenn ich ein Instagram-Bild poste, dann speichere das Bild auch in meine Dropbox.
  • Wenn ich ein Instagram-Bild poste, dann schicke das Bild als natives Bild zu Twitter.
  • Wenn dies, dann das…

Und der letzte Punkt sieht in der IFTTT-App dann so aus:

So einfach ist es also, die Instagram-Bilder schön zu Twitter zu schicken. Aber auch darüber hinaus sind die Möglichkeiten von IFTTT endlos, es gibt auch schon sehr viele fertige Applets.

Nur am Rande: Für alle Bastler ist auch der Maker-Kanal interessant, mit dem man sehr leicht z.B. mit Arduino-kompatiblen Boards kommunizieren kann. Aktuelles Bastelprojekt von mir: Ich hätte gerne eine Benachrichtigung, sobald die Waschmaschine fertig ist. Im Moment scheitert das noch am sicheren Erkennen des Endes des Waschgangs (nach dem Schleudern), aber wäre dieses Problem gelöst wäre der Rest einfach: Das Wemos D1 mini hängt im WLAN und ruft – sobald es eben das Ende des Schleuder-Vorgangs erkannt hat (siewissenschonsiewissenschon) – eine bestimmte IFTTT-URL mit einem Authentifizierungscode auf. Das ist der Trigger, der dann wieder eine Action auslösen kann, eben beispielsweise eine Benachrichtigung auf’s Handy schicken. Für Statistikfreaks könnte der Trigger auch die Uhrzeit in eine Google Tabelle schreiben, mit der man dann auswerten könnte, wie oft man die Waschmaschine nutzt, welche Wochentage Waschtage sind oder was die präferierten Waschzeiten sind. (Über die Sinnhaftigkeit kann gerne diskutiert werden…)

Arduino-Bastelei: Backup-Festplatte einschalten (lassen)

Arduino Pro Micro mit Relais

Nach meiner ersten und für den Anfang etwas aufwendigen Arduino-Bastelei war neulich Bedarf für ein zweites, diesmal sehr überschaubares Projekt: Das Einschalten einer USB-Backupfestplatte genau dann, wenn sie auch gebraucht wird.

Der Hintergrund ist der: Bei einem Rechner wird mit dem sehr empfehlenswerten Tool HardlinkBackup beim Herunterfahren des Rechners ein „inkrementelles“ Backup erstellt, und zwar mittels Hardlinks. Kurz gesagt macht man ein Vollbackup mit dem Platzbedarf eines inkrementellen Backups. Das aber nur am Rande, wäre ein Thema für sich. Das Backup wird jedenfalls automatisch gestartet, sobald Windows heruntergefahren wird. An dieser Stelle sollte die USB-Festplatte, auf die gesichert wird, dann auch verfügbar sein und nicht manuell eingeschaltet werden müssen. Dauerhaft laufen soll sie natürlich auch nicht, wenn der Rechner läuft. Das ist erstens nicht gut für die Lebensdauer der Platte, und zweitens nicht gerade sicher im Hinblick auf diverse Schadsoftware etc. Eine Möglichkeit wäre es, die Platte per Software erst einzubinden, wenn sie gebraucht wird, ich wollte sie aber hardwareseitig wirklich komplett ausgeschaltet haben.

Arduino Pro Micro

Und hier kommt wieder der kleine und günstige Arduino Pro Micro ins Spiel. Der kann – wie so ziemlich jeder andere Arduino auch – nämlich erstens per USB serielle Kommandos empfangen und verarbeiten, und zweitens dadurch getriggert dann z.B. über ein Relais die Stromversorgung der USB-Platte anschalten. Die Kosten für den Arduino plus das Relais liegen zusammen bei ca. 10€.

Und genau so wurde das auch umgesetzt. Mittels eines kleinen Tools namens SerialSend schickt der Rechner eine Kommando an die entsprechende USB-Schnittstelle, an der der Arduino hängt:


SerialSend.exe /baudrate 9600 /devnum 18 SwitchRelayON

Auf dem Arduino läuft dann folgender Sketch, der dieses Kommando empfängt und dann das an ihm an Pin 15 angeschlossene Relais schaltet:


// Define Relay Pin:
#define PinRelay 15

// Define string for relay status:
String SerialRead     = "SwitchRelayOFF";
String SerialReadOld  = "SwitchRelayOFF";

void setup() {
  
  // Define Pin mode:
  pinMode(PinRelay, OUTPUT);
  
  // Switch the relay OFF:
  digitalWrite(PinRelay, HIGH);

  // Turn serial monitor on:
  Serial.begin(9600);
  
}

void loop() {

  // Read data from serial port:
  if(Serial.available()>0) {
    SerialRead = Serial.readString();
  }

  // Only send command if status changed:
  if (SerialRead != SerialReadOld) {
    // Switch Relay:
    if (SerialRead == "SwitchRelayON") {
      digitalWrite(PinRelay, LOW);
      Serial.println("relay switched ON");
    } else if (SerialRead == "SwitchRelayOFF") {
      digitalWrite(PinRelay, HIGH);
      Serial.println("relay switched OFF");
    } 
  }

  SerialReadOld = SerialRead;
  
//  delay(1000);
  
}


Das SerialSend-Kommando wurde dann noch in das .bat-Skript integriert, welches sowieso schon beim Herunterfahren des Rechners das Backup angefahren hat:


@echo off


REM Platte über Arduino starten:
"C:\Users\Blablabla\Documents\backup-Sachen\SerialSend.exe" /baudrate 9600 /devnum 18 SwitchRelayON
timeout /T 20 > nul


REM Abbruch, falls Festplatte nicht erreichbar
if not exist "B:\" goto NoUSB:

REM Möglichkeit bieten, um Backup noch manuell abzubrechen:
Choice /T 15 /D J /M "Das Backup wird in 15 Sekunden automatisch gestartet. 'N' bricht ab... "
If Errorlevel 2 goto Abbruch:
If Errorlevel 1 goto StarteBackup:

REM Starte Backup
:StarteBackup
echo.
echo Starte das Backup, bitte warten...
cd "C:\Users\Blablabla\Documents\backup-Sachen\"
REM call "USB-Backup.hbd"
"C:\Program Files\Lupinho.Net\HardlinkBackup\HardlinkBackup.exe" -execute USB-Backup.hbd
echo Backup fertig!
Goto eof:

REM Ausgabe und Abbruch, falls Festplatte nicht erreichbar
:NoUSB
echo .
echo USB-Festplatte nicht gefunden!
Goto eof:

REM Abbruch
:Abbruch
echo .
echo Dann eben nicht...
Goto eof:

REM Sprungmarke, um Batch-Datei von jeder Stelle aus zu beenden:
:eof

Fast vergessen: Durch das Relais muss natürlich noch die Stromversorgung der USB-Platte laufen. Am besten hinter dem Netzteil einfach das Kabel aufgetrennt und eine der beiden Kabel durchgetrennt und durhc das Relais schleifen. In diesem Fall habe ich parallel noch einen ganz normalen Kippschalter gehängt, damit man die Platte auch ohne den Arduino per Hand einschalten kann, wenn man das mal möchte.

Das war’s dann auch schon. Fährt man jetzt den Rechner herunter hört man das kurze Klacken des Ralais, dann das Anlaufen der USB-Platte, anschließend startet das Backup und schließlich freut sich der Benutzer.

Arduino-Bastelei: Pedal zum Bass-Üben

Eines vorneweg: Auch wenn ich gern an allem möglichen herumbastle, bei Elektronik hört bei mir der Spaß schnell auf. Ich tausche schon mal defekte Kondensatoren in Netzteilen oder mache aus zwei defekten Kaffeemaschinen eine funktionierende, aber da müssen die defekten Stellen schon durch Rauch oder Feuer auf sich aufmerksam machen. Das große Verständnis von Elektronik fehlt mir. Etwas neidisch beobachtete ich bisher die Bastlerszene, die mit diversen günstigen Bauelementen allen möglichen Kram zusammenzaubert. Und immer wieder hörte ich, dass das alles mittlerweile gar nicht mehr schwer sei. Jeder könne das. Dabei viel immer wieder das Stichwort Arduino.

Im Sommer dachte ich, es wird auch für mich Zeit, mich da mal ein bisschen einzuarbeiten. Also habe ich einen bunten Strauß an Arduinoboards, Sensoren und Aktoren bestellt und zu basteln angefangen: Einfach mal ganz simpel einen Schalter an ein Arduinoboard und damit ein Schrittmotor steuern. Oder mit einem Näherungssensor ein Servo. Oder einfach nur eine LED blinken lassen (ein Unterfangen, an dem ich mit einer analogen Schaltung schnell scheitern würde). Mein Fazit ist: Wer googlen kann, der kann auch Arduino.

Bei diesen Spielereien habe ich irgendwann gelesen, dass diverse Arduinoboards, die ja einfach über die USB-Schnittstelle programmiert werden können, am Rechner auch gleichzeitig als Human Interface Device agieren können, sich also wie eine Maus oder eine Tastatur verhalten. Es ist also relativ leicht, sie als externes Eingabegerät für den Rechner zu verwenden. Dazu sind auch keine speziellen Treiber am Rechner nötig. Board an den USB-Anschluss und fertig.

Die Idee

Damit war die Idee geboren: Beim Bass-Üben stört es mich immer wieder, das Instrument aus der Hand legen zu müssen, um in Spotify nochmal zum Songanfang zu springen, in Youtube-Tutorials vor- oder zurückzuspulen, eine Webseite mit Chords weiterzuscrollen oder einfach nur die Lautstärke des PCs anzupassen. Ich übe in der Regel mit Kopfhörer an einem kleinen Mischpult, an dem auch der Rechner hängt, der mich mit Musik und Tutorials versorgt. Was es braucht ist eine Möglichkeit, diverse Funktionen des Rechners mit den Füßen zu steuern. Sollte mit einem kleinen Arduino machbar sein. Weiterlesen

Korrrrekte Aussprache, mit Beispielsatz

Dieser Luksan Wunder (@WTFabrik) ist hilfsbereit, und er hat Humor. Auf seinem Youtube-Kanal lehrt er uns die korrrrekte Aussprache von schwierigen Wörtern. Mit Beispielsatz:

Die richtige Aussprache von schwierigen deutschen Wörtern und Fremdwörtern – mit Beispielsatz.

einfach und zuverlässig Deutsch lernen.

Uns bleibt nur Dankbarkeit.


Weiterlesen

OAuth 2.0 – Lord, have mercy!

OAuth 2.0

Es gelingt mir nicht immer, auf dem Laufenden zu bleiben, was technische Entwicklungen im Web angeht. Vorsichtig ausgedrückt. Obwohl ich mich durchaus bemühe. Aber da draußen ist einfach zu viel los. So ging es auch an mir vorbei, dass Google angekündigt hatte, seinen Client-Login im April 2015 abschalten zu wollen. Oder ich habe einfach nicht verstanden, dass mich das betrifft. Hat es mich aber, und das gleich an verschiedenen Stellen.

Zum einen nutze ich an verschiedenen Stellen im Netz die Möglichkeit, Daten aus Google Tabellen auszulesen und diese weiter zu verarbeiten. Dieser Weg hat im Gegensatz zur Nutzung einer Datenbank den Charme, dass auch eine technisch nicht so versierte Gruppe von Usern sehr leicht Daten editieren kann, die dann direkt auf irgendwelchen Webseiten dargestellt oder für andere Dienste verarbeitet werden können.

Zum anderen brauchte ich diese Art der Authentifizierung für das Backup meiner Google Kontakte auf dem Raspberry Pi. Ich hatte darüber mal ausführlich geschrieben.

Die Nutzung des Client-Logins sah (vereinfacht) so aus, dass man sich bei Google-APIs mit seinen Google-Zugangsdaten authentifizieren konnte. Einen Schritt besser war es schon, dazu eine sog. „anwendungsspezifisches Passwort“ zu verwenden. D.h. man generierte sich bei Google ein weiteres Passwort, welches dann nur eine einzige Anwendung verwenden durfte. Vorteil: Durch Löschen des vergebenen Passworts war auch der Anwendung der Zugriff auf die Daten entzogen, außerdem musste man nicht sein richtiges Google-Passwort in irgendwelchen Skripten hinterlegen. Umgesetzt hatte ich das alles mit Hilfe des Zend Frameworks.

Diese Möglichkeit gibt es jetzt nicht mehr. OAUth 2.0 ist angesagt. OAuth ist an sich nichts neues, aber das Ding ist einfach deutlich komplexer als die herkömmliche Authentifizierung. Wie OAuth 2.0 funktioniert genau funktioniert erkläre ich hier nicht weiter, man kann das z.B. hier schön nachlesen. Ein Artikel in 5 Teilen, das sagt schon alles. Die Grundidee ist die, dass eine Anwendung einen z.B. auf eine Google-Seite weiterleitet, man sich dort authentifiziert und somit seiner Anwendung bestimmte Rechte zuweist, ohne dass die Anwendung Details der Zugangsberechtigung erhält. Das typische „Loggen Sie sich einfach mit Facebook ein“-Ding. Der große Vorteil ist hier, dass keine Passwörter weitergegeben werden, sondern lediglich sog. Access-Tokens generiert werden, die in der Regel auch eine Verfallsdatum haben. Alles crispy, alles funky, aber eben auch alles etwas komplizierter.

Wie gesagt war der Anlass, mich wieder mal mit dem Thema zu befassen, die Reaktivierung des Backups meiner Google Kontakte mit dem Raspberry Pi. Deshalb werde ich hier mal kurz umreißen, wie das Prozedere jetzt aussieht.

Der PHP-Code

Mir ist klar, dass sich meine PHP-Künste im Rahmen halten. Der Code hier ist also nur zum Hausgebrauch und als Arbeitsgrundlage für weitere Optimierungen geeignet. Außerdem enthält er eine Reihe an Kommentaren, die eher den Stil eines Selbstgesprächs als einer sinnvollen Code-Kommentierung haben. Egal.


<?

		// Backup der Google Kontakte per Cronjob funktioniert nur noch mit OAuth2

		// Es gäbe jetzt 2 Wege:

		// 1) User authentifiziert sich per Web

		// 	Problem:
		// 	- Die Authentifizierung läuft schnell ab.
		// 	- Daher ist das per Skript nicht praktikabel.

		// 2) Authentifizierung über ein "Dienskonto" ("service account") mit einem P12-Schlüssel

		// 	Problem:
		// 	- Das Dienstkonto mit seiner speziell generierten Mailadresse kann sich zwar dauerhaft authentifizieren,
		// 	  hat aber keinen Zugriff auf die Kontakte des Users, der das Dienstkonto erstellt hat...

		// Hinweise:

		// - Erstellen eines Projekts bei Google und erzeugen der Schlüssel:		https://console.developers.google.com/project
		// - API Client Library for PHP:											https://developers.google.com/api-client-library/php/start/get_started
		// - Google Contacts API version 3.0:										https://developers.google.com/google-apps/contacts/v3/index#retrieving_all_contacts
		// - google-api-php-client:													https://github.com/google/google-api-php-client
		// - Beispielcode für Ahthentifizierung per Web:							https://github.com/google/google-api-php-client/issues/462
		// - Warum es nicht geht, sondern nur mit einer "Google managed domain":	http://stackoverflow.com/questions/14407415/accessing-google-contacts-api-via-oauth-2-0-and-private-key-aka-service-account
		// - Vielleicht geht es doch per Web-Authentifizierung???					http://stackoverflow.com/questions/13851157/oauth2-and-google-api-access-token-expiration-time

		//  >>> However, after a successful completion of the OAuth2 installed application flow,
		// 		you will get back a refresh token.
		// 		This refresh token never expires, and you can use it to exchange it for an access token as needed.
		// 		Save the refresh tokens, and use them to get access tokens on-demand
		// 		(which should then immediately be used to get access to user data).

# Debug-Modus. Wenn der TRUE ist werden nur Debug-Infos rausgeschickt:
define("DEBUGMODUS", FALSE);

# # # # VERSION MIT DER WEB-AUTHENTIFIZIERUNG

	# Diese Daten hier erhält man nach der Registrierung eines Projekts in der Developers Console (https://console.developers.google.com/):
	# Client-ID:
	$client_id 		= 'HIER KOMMT DEINE CLIENT-ID REIN';
	# Clientschlüssel:
	$client_secret 	= 'HIER KOMMT DEIN CLIENT-SCHLÜSSEL REIN';

	# Nach dem ersten Aufruf des Skripts per Webbrowser bekommt man einen RefreshToken,
	# den man hier einträgt. Mit diesem kann dann bei jedem weiteren Aufruf
	# ein neuer AccessToken geholt werden, mit dem dann wiederrum die Daten geholt werden:
	$refresh_token = 'HIER KOMMT DEIN REFRESH-TOKEN REIN';

	/*
	 * Copyright 2011 Google Inc.
	 *
	 * Licensed under the Apache License, Version 2.0 (the "License");
	 * you may not use this file except in compliance with the License.
	 * You may obtain a copy of the License at
	 *
	 *     http://www.apache.org/licenses/LICENSE-2.0
	 *
	 * Unless required by applicable law or agreed to in writing, software
	 * distributed under the License is distributed on an "AS IS" BASIS,
	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	 * See the License for the specific language governing permissions and
	 * limitations under the License.
	 */

	# Falls das Skript per Kommandozeile ausgeführt werden soll sollen die Fehler unterdrückt werden (z.B. die Warnings wg. der Session):
	if ($refresh_token)	error_reporting(0);

	session_start();

	// # Session manuell killen, und damit neue Token erzwingen:
	// unset($_SESSION['access_token']);

	# Diese Library muss eingebunden werden: https://github.com/google/google-api-php-client
	require_once __DIR__ . '/google-api-php-client-master/examples/templates/base.php';
	require_once __DIR__ . '/google-api-php-client-master/src/Google/autoload.php';

	$scriptUri 		= "http://".$_SERVER["HTTP_HOST"].$_SERVER['PHP_SELF'];
	$redirect_uri 	= $scriptUri;

	/************************************************
	  Make an API request on behalf of a user. In
	  this case we need to have a valid OAuth 2.0
	  token for the user, so we need to send them
	  through a login flow. To do this we need some
	  information from our API console project.
	 ************************************************/
	$client = new Google_Client();
	$client->setClientId($client_id);
	$client->setClientSecret($client_secret);
	$client->setRedirectUri($redirect_uri);
	//$client->addScope("https://www.googleapis.com/auth/contacts.readonly");
	$client->addScope("https://www.google.com/m8/feeds");

	# HIER KOMMT DER ENTSCHEIDENDE PUNKT!
	# Der AccessToken soll OFFLINE sein, d.h. ich bekomme auch einen 'refresh_token',
	# mit dem ich mir dann immer wieder neu einen 'access_token' holen kann,
	# ohne die Web-Authentifizierung neu machen zu müssen.
	# Siehe https://developers.google.com/identity/protocols/OAuth2WebServer#refresh
	# PHP-Demo: http://stackoverflow.com/questions/9241213/how-to-refresh-token-with-google-api-client
	# Außerdem muss dazu noch approval_prompt=force gesetzt werden.
	# Siehe https://github.com/google/google-api-php-client/issues/263
	$client->setAccessType('offline');
	$client->setApprovalPrompt('force');

	/************************************************
	  Boilerplate auth management - see
	  user-example.php for details.
	 ************************************************/
	if (isset($_REQUEST['logout'])) {
		unset($_SESSION['access_token']);
	}
	if (isset($_GET['code'])) {
		$client->authenticate($_GET['code']);
		$_SESSION['access_token'] = $client->getAccessToken();
		$redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
		header('Location: ' . filter_var($redirect, FILTER_SANITIZE_URL));
	}

	if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
		$client->setAccessToken($_SESSION['access_token']);
	} else {
		$authUrl = $client->createAuthUrl();
	}

	# Falls schon ein RefreshToken gesetzt ist kann das Skript per Kommandozeile ausgeführt werden:
	if ($refresh_token) {

		# Damit hole ich mir bei JEDEM Aufruf einfach einen neuen Access-Token ;-)
		$client->refreshToken($refresh_token);

		# Außerdem die Variable $authUrl löschen, sonst wird weiter unten nur die URL zum Login angezeigt:
		unset($authUrl);
	}

	/************************************************
	  If we're signed in, retrieve contacts
	 ************************************************/
	if ($client->getAccessToken()) {

		if (DEBUGMODUS) echo "<hr><h1>Session-Variablen:</h1><pre>".print_r($_SESSION, true)."</pre>";

		$_SESSION['access_token'] = $client->getAccessToken();

		$access_token = json_decode($client->getAccessToken())->access_token;
		if (DEBUGMODUS) echo "<hr><h1>Client:</h1><pre>".print_r($client, true)."</pre>";
		if (DEBUGMODUS) echo "<hr><h1>Access-Token:</h1><pre>".print_r(json_decode($client->getAccessToken()), true)."</pre>";
		if (DEBUGMODUS) echo "<hr><h1>Weitere Infos zum Access-Token:</h1><pre>".print_r(json_decode(file_get_contents('https://www.googleapis.com/oauth2/v3/tokeninfo?access_token='.$access_token)), true)."</pre>";

		# Beim ersten Aufruf soll einfach nur der Refresh-Token zurückgegeben werden, der muss dann hier ins Skript eingetragen werden:
		if (!$refresh_token) {
			echo "Bitte den Code unterhalb der Linie in das Skript in die Variable $refresh_token eintragen:<hr>";
			echo "<pre>".json_decode($client->getAccessToken())->refresh_token."</pre>";
			exit();
		}

		//$url = 'https://www.google.com/m8/feeds/contacts/default/full?max-results=3&alt=json&v=3.0&oauth_token='.$access_token;
		$url = 'https://www.google.com/m8/feeds/contacts/default/full?max-results=3000&alt=json&v=3.0&oauth_token='.$access_token;

		$response =  file_get_contents($url);

	}
	if (isset($authUrl)) {
		echo "<a class='login' href='" . $authUrl . "'>Zugriff auf Google Contacts autorisieren > KLICK!</a>";
	} else {
		if (DEBUGMODUS) echo "<hr><h1>Kontakte:</h1><pre>".print_r(json_decode($response), true)."</pre>";
		else echo $response;

	}

Dieses Skript muss auf den Raspberry Pi kopiert und so eingerichtet werden, dass es (vorübergehend) aus dem Netz erreichbar ist. Man sollte also irgend einen Webserver auf dem Pi laufen haben.

Außerdem braucht man den Google API PHP-Client, den man herunterladen und in sein Projekt einbinden muss. Könnte man auch per Composer machen, ist in diesem Fall aber vielleicht ein bisschen zu viel des Guten. Immerhin gibt es keine Abhängigkeiten von anderen Paketen.

Die Authentifizierung

Um dem Skript nun Zugriff auf die eigenen Daten zu gewähren, muss in der Google Developers Console ein neues Projekt angelegt werden: https://console.developers.google.com/ Das Projekt braucht einen beliebigen Namen. Außerdem muss man folgende APIs aktivieren:

  • Contacts API
  • Google Contacts CardDAV API
  • Google Partners API

Bin mir nicht wirklich sicher, ob man die „Google Contacts CardDAV API“ hier auch braucht, aber sie schadet nicht…

Anschließend brauchen wir Zugangsdaten, die wir (tataaa!) unter „Zugangsdaten“ generieren. Und zwar wählen wir „Client-ID für Webanwendung erstellen“. Wichtig ist an dieser Stelle, dass eine Weiterleitungs-URI gesetzt wird, die auf genau die URL zeigt, unter der unser PHP-Skript gerade im Netz erreichbar ist. Wenn wir die Client-ID erstellt haben bekommen wir unter anderem folgende Parameter: Eine „Client-ID“ und einen sog. „Clientschlüssel“. Diese beiden Werte müssen wir jetzt in unser PHP-Skript eintragen:


# Diese Daten hier erhält man nach der Registrierung eines Projekts in der Developers Console (https://console.developers.google.com/):
 # Client-ID:
 $client_id = 'HIER KOMMT DEINE CLIENT-ID REIN';
 # Clientschlüssel:
 $client_secret = 'HIER KOMMT DEIN CLIENT-SCHLÜSSEL REIN';

Wenn wir jetzt das PHP-Skript vom Web aus aufrufen, können wir den bekannten Authentifizierungsprozess starten: Das Skript leitet weiter zu einer Google-Authentifizierungsseite, dort sollte man dann alles gut finden und brav bestätigen, und am Ende wird man zurück zu unserem Skript geleitet. Das Skript ist jetzt authentifiziert, die Kontakte bei Google abzuholen. Allerdings verfällt der dazu vergeben Access Token schon innerhalb einer Stunde. Unpraktisch, wenn das Skript die Kontakte z.B. täglich ohne Zutun des Nutzers sichern soll. Daher wird von Google gleichzeitig ein sog. „Refresh Token“ angefordert. Mit Hilfe dieses Refresh Tokens kann das Skript bei jedem Aufruf einen neuen Access Token anfordern und anschließend mit diesem die Kontakte anfordern. Dazu muss man den Refresh Token irgendwo hinterlegen. Üblicherweise macht man das in einer Datenbank, der Einfachheit halber speichern wir ihn aber direkt im Skript. Das Skript zeigt den Refresh Token nach erfolgreicher Authentifizierung im Browser an, von dort kopieren wir ihn jetzt in unser Skript:


# Nach dem ersten Aufruf des Skripts per Webbrowser bekommt man einen RefreshToken,
# den man hier einträgt. Mit diesem kann dann bei jedem weiteren Aufruf
# ein neuer AccessToken geholt werden, mit dem dann wiederrum die Daten geholt werden:
$refresh_token = 'HIER KOMMT DEIN REFRESH-TOKEN REIN';

Die Ausführung

Ein Zugriff auf das Skript über das Internet ist nun nicht mehr nötig und sollte auch unterbunden werden. Denn ab jetzt soll das Skript nur noch per Kommandozeile oder Crontab ausgeführt werden, z.B. so:

php ~/skripte/backup-google-contacts.php | gzip > ~/backup/Google\ Kontakte/backup-google-contacts-`date +\%Y-\%m-\%d`.json.gz

Geschafft! Ich hoffe, der eine oder andere kann etwas mit dem Code-Chaos hier anfangen. Der Code sollte auf jeden Fall ein paar Anhaltspunkte für jemanden enthalten, der vor ähnlichen Problemen steht. Ich glaube, mir hätte das eine oder andere Code-Schnipsel weitergeholfen und mir die eine oder andere Nachtschicht erspart. Wobei, wäre vielleicht sogar schade gewesen, so ein Erfolgserlebnis ist ja auch was wert 😉

Roboter für Dominosteine

Lange Zeit hat uns (also meinen Jungs und mir) eine gute Idee gefehlt für eine erste größere Eigenentwicklung mit  unserem LEGO MIndstorms EV3. Denn eine gute Idee muss her, sonst bleibt das Projekt spätestens auf halber Strecke stecken. Da der Jüngere sehr gerne mit Dominosteinen spielt (während ich Dominosteine vor allem gerne esse, aber das ist ein anderes Thema) und wir immer mal wieder Maschinen gesehen haben, die Dominosteine aufstellen, wollten wir das mal angehen: Einen Roboter zum Aufstellen von Dominosteinen. Gut, hierzu gibt es auch schon einige inoffizielle LEGO Mindstorms-Modelle, neu an unserem ist aber, dass er mit einem Abstandssensor selbständig feststellt, wann das Steine-Reservoir leer ist und neue Steine nachgelegt werden müssen.

Die Entwicklung des Modells hat sich inkl. der Programmierung über einige Wochen hingezogen. Es musste ständig sowohl an der Hard- als auch an der Software nachgebessert werden, bis das Teil einigermaßen zuverlässig funktioniert hat. Als problematisch stellen sich vor allem unsere recht kleinen und leichten Dominosteine heraus. Mit ordentlichen Holzsteinen dürfte das alles deutlich stabiler hinzubekommen sein.

Hier ein kleiner Einblick ins fertige Modell:

Nachdem das Modell fertig war haben wir es im LEGO Digital Designer nachgebaut. Das ist eine Software, mit der man seine Lego-Modelle nach ein bisschen Einarbeitungszeit relativ flott modellieren und somit auch konservieren kann. Unser Modell kannst du hier herunterladen und im LEGO Digital Designer importieren. Damit sollte ein Nachbau ziemlich einfach möglich sein. Die Software erstellt aus dem digitalen Modell auf Wunsch auch (mehr schlecht als recht) eine schrittweise Bauanleitung, die wir hier mal als PDF zur Verfügung stellen. Zu guter Letzt haben wir das Modell auch noch auf in die LEGO Digital Designer Gallery hochgeladen.

Was dann zum Nachbau natürlich noch fehlt ist die Software. Das Programm muss sicherlich für andere Dominosteine hier und da anders justiert werden. Unseres sieht folgendermaßen aus:

Domino Bricks - Software

 

Herunterladen kannst du das Programm hier.

 

 

 

Raspberry Pi als Backupmaschine

Raspberry PiDer Raspberry Pi ist eine kleine Allzweckwaffe: Ein kompletter Rechner für ca. 35€, so groß wie eine Scheckkarte und mit einer sehr geringen Leistungsaufnahme (deren Kehrseite natürlich auch eine ziemlich geringe Leistung ist). Aber für manche Anwendungsfälle ist der Raspberry Pi genau das richtige Gerät. Ich kenne einige Leute, die sich vor lauter Begeisterung einen Raspberry Pi gekauft haben und nun nicht so richtig wissen, was sie mit dem schicken Teil nun eigentlich anfangen sollen. Mein Tipp: Als Backupmaschine verwenden.

Was der Raspberry Pi bei mir alles so backupt will ich in diesem Beitrag grob skizzieren. Voraussetzung ist ein fertig installiertes Raspian oder ein vergleichbares System, Grundkenntnisse im Umgang mit Linux (z.B. der crontab), dem Raspberry Pi an sich und zumindest eine gewisse Lernbereitschaft und Offenheit gegenüber z.B. Shell- und PHP-Skripten. Ich werde keine kompletten Anleitungen schreiben, eher so eine Gedankensammlung. Es muss und soll also weiter gebastelt und gegooglet werden!

Weiterlesen

Passwortmanager: KeePass oder nix

Passwörter braucht man heutzutage ja an jeder Ecke, und im Umgang mit Passwörtern kann man so einiges falsch machen: Die Hitliste der am häufigsten verwendeten Passwörtern verschlägt einem die Sprache. Und das ist nur die Spitze des Eisbergs.

Was bisher geschah

Ganz so fahrlässig hatte ich das bisher nicht gehandhabt. Ich hatte schon ein ziemlich ausgeklügeltes System, bei dem ich… Lassen wir das besser. Immerhin hatte ich nicht bei jedem Dienst das selbe Passwort. Richtig verlässlich fand ich das alles trotzdem nicht. Vor allem kann man – vergibt man Passwörter nach einem System – nicht mal so einfach hier oder da ein Passwort ändern, nur weil von diesem Dienst gerade die Passwörter entwendet wurden. Ungefährlich ist ein sorgloser Umgang mit Passwörtern auch nicht, in regelmäßigen Abständen wird z.B. mit geklauten Passwörtern viel Schaden angerichtet (nicht nur finanzieller). Wenn du denkst, das wäre alles halb so wild, dann gib doch mal testweise nur ein einziges deiner Passwörter an deine fünf besten Freunde: Dein Mailpasswort. Na also.

Mein Plan

Ich wollte das endlich besser geregelt haben. Nein, nicht besser, sondern gut. Dazu braucht man 1) für jeden Dienst ein separates Passwort, welches 2) zufällig generiert und ausreichend lange ist. Wenn man diese Anforderungen stellt, führt kein Weg an einem Passwortmanager vorbei. Ein Passwortmanager funktioniert so, dass man alle seine tollen Passwörter in eine Art digitales Safe speichert und sich nur den einen (richtig gut ausgedachten!) Schlüssel dazu merken muss, das Masterpasswort.

Weiterlesen

Rechts-Äuger

Bildungslücke! Ich wusste zwar, dass ich zwei Augen habe, und dass ich – da beide ganz ordentlich funktionieren – damit auch räumlich sehen kann. In meinem symmetrischen Denken bin ich davon ausgegangen, dass es daher auch gut wäre, wenn beide Augen gleich viel zu meinem visuellen Eindruck beitragen würden. Pustekuchen.

Im Zusammenhang mit dem Projekt Google Glass bin ich über ein Video und darin zum ersten Mal über den Begriff der „Augendominanz“ gestolpert. Augendominanz bedeutet grob gesagt, dass das Gehirn bei der Berechnung des visuellen Eindrucks die Informationen des einen Auges denen des anderen Auges vorzieht. Um festzustellen, welches Auge bei dir dominant ist, kannst du folgenden recht einfachen Test durchführen:

Zur Feststellung der Augendominanz gibt es verschiedene Verfahren. Bei vielen wird die Versuchsperson darum gebeten ein näheres (beispielsweise den eigenen Daumen bei ausgestreckten Arm) und ein ferneres Objekt (beispielsweise ein senkrechter Strich an einer Wand) aufeinander abzustimmen (beispielsweise den Daumen so zu positionieren, dass er auf dem Strich liegt) und das nähere Objekt zu fixieren. Nun wird die Versuchsperson gebeten die Augen abwechselnd zu schließen. Schließt sie das nicht dominante Auge verändert sich die wahrgenommene Position der Objekte zueinander nicht, da die binokuläre Wahrnehmung ohnehin auf das dominante Auge abgestimmt ist. Schließt die Versuchsperson jedoch das dominante Auge verändert sich die Position der Objekte zueinander, da die visuelle Information des nicht dominanten Auges nicht mehr an die des dominanten Auges angepasst werden kann.

via de.wikipedia.org

Ergebnis: Ich bin Rechts-Äuger.

Scratch

Man ist als Vater ja bestrebt, den Spösslingen einiges für’s Leben mitzugeben. Neben zweitrangigen Dingen wie Werten gibt es auch die richtig wichtigen wie Spaß an Technik oder Programmierung. Für Letzteres fehlte mir bisher aber das richtige Tool, nämlich eine Porgammiersprache für Kinder. Vor dem Urlaub bin ich endlich fündig geworden: Scratch.

Damit haben wir im Urlaub dann ein bisschen gebastelt. Herausgekommen sind zwei kleine Spielchen, die zwar noch ziemlich rudimentär und auch buggy sind, bei deren Ersellung die Jungs trotzdem spielerisch einige Grundkonzepte der Programmierung kennengelernt und dann auch selbst angewendet haben: Bedingungen, Schleifen, Objekte, Funktionen, Variablen, Events etc.

Hier unsere bisherigen zwei Projekte. Die Ideen stammen von den Jungs (sag ich jetzt mal so, um mich bei dem Shooter herauszureden…), bei der Umsetzung war ich größtenteils dabei, einige Programmteile sind dann aber auch ohne mich entstanden.

Scratch Project

Scratch Project

Schön ist auch der Community-Aspekt von Scratch. Somit kann man sich den „Code“ von anderen einfach ansehen, damit weiterarbeiten oder einfach davon lernen.