Steuerung per SMS

Der Raspberry Pi kann natürlich problemlos mit vielen, aktuellen 3G-USB-Sticks arbeiten und z.B. SMS versenden. Aber ich möchte hier auch zeigen, dass man zusätzlich SMS empfangen und auswerten kann um z.B. bestimmte Jobs remote zu starten, ohne dass der Pi über das Internet erreichbar ist.

Als erstes brauchen wir einen 3G-Stick. Ich habe hier z.B. den Vodafone K3565-Z Stick. Für dieses Modell gibt es bereits Nachfolgemodelle, die aber ebenfalls funktionieren.

Als erstes sind ein paar Softwarepakete zu installieren, damit der Stick überhaupt erkannt wird und angesprochen werden kann. Dazu geben wir die folgenden zwei Befehle ein:

sudo apt-get update
sudo apt-get install gammu libgammu-i18n libgammu7 libjim0debian2 usb-modeswitch usb-modeswitch-data

Nach dieser Installation könnte man den Stick z.B. direkt dafür verwenden, eine Internetverbindung per UMTS aufzubauen. Hier wollen wir aber mit SMS arbeiten und brauchen dafür das Sende- und Empfangstool gnokii. Es gibt weitere SMS-Tools, die aber entweder komplizierter in der Anwendung sind oder nicht alle Funktionen abdecken.

Die Installation erfoltgt mittels:

sudo apt-get install gnokii

Nach der Installation ist es Zeit, den UMTS-Stick mit einer aktiven Mobilfunkkarte an den Raspberry Pi anzuschließen und diesen einmal zu rebooten.

Nun muss der eingesetzte UMTS-Stick eingerichtet werden. Das dieses je nach Modell unterschiedlich ist, beschreibe ich hier das Vorgehen für den oben bereits erwähnten Vodafone K3565-Z  Stick. Dieser richtet sich eigenständig mit vier USB-Devices ein (/dev/ttyUSB0 … /dev/ttyUSB3).

Als erstes legen wir nun die Konfigurationsdatei für gnokii an. Diese liegt standardgemäß im Home-Verzeichnis des ausführenden Users in einem Unterverzeichnis. Beispiel für den User zabbix:

/home/zabbix/.config/gnokii/config

Also legen wir zuerst das Verzeichnis an.

mkdir -p /home/zabbix/.config/gnokii

Wir sollten dieses als der Bentzer tun, dessen Home-Verzeichnis wir verwenden. Ansonsten sind die Berechtigungen nicht richtig gesetzt und müssen manuell geändert werden.

Die Datei „config“ editieren wir mit

nano /home/zabbix/,.config/gnokii/config

und schreiben die folgenden Zeilen für das Ansprechen des Sticks hinein:

[global]
port = /dev/ttyUSB3
model = AT
connection = serial

Nun muss noch das Verzeichnis für die Log-Datei angelegt werden. Dieses erledigen wir mit

mkdir -p /home/zabbix/.cache/gnokii

Dort schreibe gnokii dann eine Datei names „gnokii-errors“ hinein, die dann auftretende Fehler enthält.

 

Versand und Empfang von SMS

Info: Ich habe aus kostengründen derzeit einen relativ optimalen Tarif bei http://www.winsim.de gefunden. Hier handelt es sich um einen Postpaid-Vertrag aber ohne Grundgebühr und je SMS 0,06 € Kosten auch preislich sehr interessant. Da es ein Vertrag ist und keine Prepraid-Karte muss man hier auch keine Angst haben, das die Karte plötzlich durch zu wenig Nutzung einfach deaktiviert wird!

Als erstes müssen wir nun den Stick mit der PIN einbuchen. Angenommen die PIN der SIM-Karte lautet 1234, so sieht der Befehl dafür wie folgt aus:

echo "1234" | gnokii --entersecuritycode PIN

Jetzt sollte der Stick eingebucht sein, und wir können zum Test eine SMS versenden. Wenn die Empfängernummer z.B. 0172-123456 lautet, geben wir folgenden Befehl ein:

echo "Dieses ist eine Test-SMS von meinem Pi!" | gnokii --sendsms +49172123456

Diese SMS sollte nun problemlos auf dem entsprechendem Handy ankommen.

Der SMS-Empfang ebenfalls einfach. Hierbei muss beachtet werden, dass der Stick zunächst die SMS empfängt und diese auf einem der 10 vorhandenen Speicherplätze der SIM-Karte speichert. Dabei wird immer bei Speicherplatz eins angefangen, sofern dieser leer ist. Folgende SMS Nachrichten werden dann in den nächst höheren Speicherplatz gespeichert. Von dort aus kann gnokii die SMS abholen und ausgeben. Das funktioniert dann mit dem Befehl:

gnokii --getsms SM 1

Dieser Befehl liest den ersten Speicherplatz aus und gibt die Nachricht direkt wieder. Ist der Speicherplatz leer erhält man folgende Nachricht:

Getting SMS failed (location 1 from SM memory)! (Der gegebene Platz ist leer.)

Mit dem folgenden Skript frage ich alle fünf Minuten den SMS-Eingang ab und reagiere, wenn ich von meinem Handy eine SMS mit einem bestimmten Befehl gesendet wurde. Dadurch kann man z.B. remote eine Fritzbox rebooten, wenn das Internet nicht mehr funktioniert:

#!/bin/bash
logfile="/var/log/check_sms_in.log"

for (( nr=0; nr<10; nr++ ))
do
sms=$(gnokii --getsms SM $nr 2>&1)
#
# Ist der Speicherplatz leer, kann das Skript beendet werden.
#
if [ "`echo \"$sms\" | grep \"(Der gegebene Platz ist leer.)\"`" ]; then
  exit 0
else
#
# Prüfen, ob der Stick eingebucht ist. Ansonsten die PIN senden zum Einbuchen.
# 
  if [ "`echo \"$sms\" | grep \"besser als garnichts\"`" ]; then
    echo "1234" | gnokii --entersecuritycode PIN
    exit 0
  fi
fi
#
# Absender-Nummer auslesen und den Befehl aus der SMS erkennen.
# Syntax für die SMS ist dann "Start.Befehl". 
#
absender=$(echo "$sms" | grep Absender: | cut -d+ -f2 | cut -d\  -f1)
#
# Den Prefix "Start." vom eigentlichen Befehl trennen
#
cmd=$(echo "$sms" | grep Start | cut -d. -f2)
#
# Prüfen, ob die SMS von meinem Handy gekommen ist.
# Handynummer ohne führendes Plus-Zeichen eintragen!
# Ist die SMS von meinem Handy, dann je nach Befehl die Kommandos ausführen.
if [ "$absender" == "49172123456" ]; then
  case "$cmd" in
   fritzreboot )
     /usr/local/bin/fritz-reboot
     echo "Fritz!Box wird gerade rebootet! Dauer ca. 2 Minuten..." | gnokii --sendsms +49172123456
   ;;

   getip )
     GETEXTIP=$(curl -0 --silent http://checkip.dyndns.org | awk '{print $6}' | cut -f 1 -d "<")
     echo "Die externe IP-Adresse ist $GETEXTIP" | gnokii --sendsms +49172123456
   ;;

   help )
     cat /usr/local/bin/check_sms_in.help | gnokii --sendsms +49172123456
   ;;

  esac
fi
gnokii --deletesms SM $nr
done

Sende ich per SMS also z.B. „Start.fritzreboot“, so wird das Skript /usr/local/bin/fritz-reboot gestartet. Bei „Start.getip“ schickt mir das Skript meine externe IP-Adresse per SMS zurück und „Start.help“ sendet mir den Inhalt der Datei /usr/local/bin/check_sms_in.help zu. Das könnten z.B. alle verfügbaren Befehle sein, wenn man die mal vergessen hat. 😉 Im Anschluß wird der Speicher dann wieder gelöscht und der nächste Speicherplatz wird abgerufen.

Dieses Skript lasse ich per Cronjob alle fünf Minuten ausführen. Man könnte dieses Skript auch als Daemon laufen lassen, allerdings verbraucht das ganze dann zu viel CPU-Leistung und in der Regel ist für diesen Zwek eine Reaktionszeit von maximal fünf Minuten vollkommen ausreichend.

Der Vollständigkeit halber hier noch das Skript, um eine Fritzbox zu rebooten:

#!/usr/bin/expect

spawn telnet 192.168.0.1
expect "password:"
send "MeinPasswort\n"
expect "# "
send "/sbin/reboot\n"
expect "# "
send "exit\n"

Hier muss nur die erste Zeile entsprechend der IP-Adresse der eigenen Fritzbox und die dritte Zeile mit dem entsprechenden Passwort geändert werden. Hinter dem Passwort muss das \n stehen bleiben, damit ein Return hinter dem Passwort gesendet wird.

 

Ändern des ttyUSB-Devices nach einem Reboot (03.04.2016)

Leider kommt es vor, dass nach einem Reboot das ttyUSB-Device, welches in der gnokii Konfigurationsdatei angegeben werden muss, ein anderes ist als zuvor. Das passiert vor allem dann, wenn man mehrere USB-Geräte am Raspberry angeschlossen hat. Hier hilft dann nur ein kleines Skript, welches gleich nach dem Booten das USB-Device sucht und die Konfigurationsdatei anpasst.

Das untenstehende Skript muss zunächst so geändert werden, dass das Skript immer nach dem richtigen Device sucht. Dazu finden wir zunächst das passende Device. Wenn wir den aktuellen ttyUSB-Port kennen, geben wir folgende beiden Befehle ein:

cd /sys/devices/platform
find . -name ttyUSB4 

In diesem Fall ist unser aktuell richtiger Port also ttyUSB4. Nun erhalten wir folgende Ausgabe:

root@raspberrypi:/sys/devices/platform# find . -name ttyUSB4
./soc/3f980000.usb/usb1/1-1/1-1.5/1-1.5:1.3/ttyUSB4
./soc/3f980000.usb/usb1/1-1/1-1.5/1-1.5:1.3/ttyUSB4/tty/ttyUSB4

Der für uns wichtige Teil ist der Verzeichnisteil bis zum ttyUSB4. Diesen Teil passen wir im folgenden Skript im fett markierten Teil an:

#!/bin/sh
port=$(ls -d /sys/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.5/1-1.5:1.3/tty*/ | cut -d "/" -f11)
port=$(echo "port = /dev/"$port)

sed 's*port = /dev/tty[A-Z]\*[0-9]*'"$port"' *' /root/.config/gnokii/config >/tmp/config
mv /tmp/config /root/.config/gnokii/.

Dieses Skript legen wir z.B. unter /usr/local/bin/set_sms_device.sh an. Nun genügt ein Eintrag in der crontab oder ein Aufruf aus der /etc/rc.local. Danach wird bei jedem Bootvorgang das korrekte Device eingetragen und der SMS-Dienst funktioniert wieder.

20 Kommentare

  1. Hallo
    Sieht ja eigendlich ganz einfach aus, nur scheitere ich leider ab dem Punkt der PIN Eingabe.
    Bekomme nur eine Fehlermeldung, dass die Konfigdatei und die Logdatei nicht gelesen werden kann und die Initialisierung der Telefonschnittstelle fehlgeschlagen ist. Der Stick selber wir aber erkannt und über ttyUSB0 bis ttyUSB3 eingebunden.
    Der Stick ist auch der Vodafone K3565-Z am RaspPi B+ mit aktuellem Rasbian

    greetz Marcel

    • Hallo Marcel,

      wahrscheinlich fehlen die entsprechenden Verzeichnisse im Home-Verzeichnis des Users, mit dem Du gnokii aufrufst. Dazu müssen dort die Verzeichnisse „.cache/gnokii“ und „.config/gnokii“ mit den Berechtigungen 755 angelegt sein. Im config-Verzeichnis solltest Du dann noch die Datei „config“ anlegen mit folgendem Inhalt:

      [global]
      port = /dev/ttyUSB3
      model = AT
      connection = serial

      Eventuell muss der Port angepasst werden. In der Regel ist aber der ttyUSB3 der richtige.

      Viele Grüße
      Thomas

    • Wenn Du im Script in der ersten Zeile „#!/bin/sh“ stehen hast, brauchst Du das „sh“ vor dem Skript nicht mehr angeben. Außerdem kannst Du im Zeitplan einfach „* * * * *“ angeben, da cron dann von alleine jede Minute ausführt. Das „/1“ ist also überflüssig.

      Wenn das Script dann immer noch nicht funktioniert, schaue mal, ob Du im messages-Log etwas findest.

  2. „Nach dieser Installation könnte man den Stick z.B. direkt dafür verwenden, eine Internetverbindung per UMTS aufzubauen. “

    Wird automatisch eine aufgebaut? Habe nämlich keine Datenflat auf meiner Prepaidkarte 🙂 Möchte nur SMS (senden)/empfangen 🙂

    • Nein. Automatisch nicht. Dazu müsste man den UMTS-Stick ja als Netzwerkdevice konfigurieren und dem Raspberry mittels Routing mitteilen, dass er den Internetverkehr aucb zum UMTS-Stick gibt. Also werden so ohne weiteres keine Daten übertragen.

      Ich besitze mit der entsprechenden SIM-Karte auch keine Internetflat. Ist nur ein Tarif. bei dem SMS günstig sind. Internet wäre bei der Karte mein finanzieller Untergang. 😉

      • Danke für deine schnelle Antwort 🙂
        Mir ist ein kleiner „Fehler“ in deinem Script aufgefallen.
        Du gehst die Nachrichten auf der SIM Karte von 1 an durch:

        for (( nr=1; nr<10; nr++ ))
        do
        sms=$(gnokii –getsms SM $nr 2>&1)

        Üblicherweise fängt man in der Informatik – Arrays und so… – (fast) immer bei 0 an zu zählen.
        So auch in dem Fall von gnokii.
        Ist zwar nicht schlimm, aber die Nachricht auf Speicherplatz 1 bleibt „ewig“ erhalten 😉

        Falls sich noch jemand wundert, warum die erste Nachricht bei einem nicht ankommt

  3. Hallo, super Anleitung, genau das was ich gesucht habe!
    Es funktioniert soweit auch ganz gut. Nur leider empfängt gnokii nach einer Zeit keine SMS mehr.
    Manuelle Überprüfung: gnokii –getsms SM 0(bzw. 1) liefert, dass eine keine SMS vorhanden ist.
    Starte ich aber den Raspberry neu gehen alle Nachrichten ein.
    Kann hier wer weiterhelfen? 1000 Dank schonmal!

  4. Hallo Frank,

    das klingt für mich danach, dass der USB-Stick nicht mehr sauber läuft. Schau mal mit lsusb, ob der Stick noch erkannt wird, wenn keine SMS mehr reinkommen. Ansonsten kann man auch noch versuchen, eine SMS zu senden. Wenn das noch funktioniert, wäre das Problem nicht mehr am Stick zu suchen.

    • Hallo Thomas,

      lsusb listet den USB-Stick auf. Dennoch kann ich keine neuen SMS empfangen.
      Erst nach dem Senden einer SMS werden neue SMS empfangen.
      Es scheint so als ob der Stick/gnokii in eine Art Standby wechselt und keine SMS mehr abfragt.

  5. Hallo Thomas,

    auch von mir zunächst einmal ganz herzlichen Dank für Deinen tollen und hilfreichen Artikel ! :-))

    Auch ich hatte prompt Erfolg mit dem Senden von SMS, der Empfang wollte aber auch bei mir nicht funktionieren. Ich habe daraufhin so einiges ausgeschlossen und probiert.

    Ich nutze einen ganz ähnlichen Stick, einen K3765 (auch ein Vodafone-Dongle).

    Die Lösung für das Nichtfunktionieren lag im Ansprechen des zutreffenden Speichers. Der ‚memory type code‘ „SM“ trifft beim K3765 nicht zu.
    Erfolg habe ich mit dem ‚Telefonspeicher‘ und dem zugehörigen ‚memory type code‘ „ME“ gehabt.
    Der Befehl lautet dann also: gnokii –getsms ME 0 (usw…)

    Fündig bin ich dazu in der Dokumentation:

    http://wiki.gnokii.org/index.php/SMS_options#–getsms

    geworden. Dort steht: „gets SMS messages from specified memory type starting at entry start and ending at end. For the memory types you usually use SM for the SIM card and ME for the phone memory. The exception are the phones supported by nk7110 (Nokia 7110/6210/6250) and nk6510 (Nokia 6310/6510/8310) drivers“

    Alle ‚memory type codes‘ sind dort auch noch einmal aufgeführt:

    http://wiki.gnokii.org/index.php/Memory_type_codes

    Das war jetzt auch ein wenig ausführlich, aber vielleicht hilft es jemanden weiter…

    Liebe Grüße

    Micha

  6. Hallo Thomas,
    geniale Anleitung – vielen Dank.
    Ich hänge an der Stelle, wo die sms im Script gelesen werden soll:
    cmd=$(echo „$sms“ | grep Start | cut -d. -f2)
    Wenn ich mit dem Befehl gnokii –getsms SM 0 die SMS aufrufe kommt:
    Text:
    smstext
    Kannst du oder jemand mir sagen, wie der Befehl aussehen müsste, damit ich den smstext bekomme?
    Gruß

  7. Hallo.
    Danke erstmal eine super Anleitung.
    Bin als Neuling ohne Kenntnisse sofort zurechtgekommen.
    Da ich von Script relativ null Ahnung habe, könntest du mir zeigen wie der Script aussehen müsste damit ich per SMS einen gpio ein/ausschalten kann?
    Ist es auch möglich das mehrerer Leute denn gpio schalten könnten und die SMS ein Passwort vor dem Befehl hätte zwecks Sicherheit?

    • Hallo Mike,

      ein direktes Ein- und Ausschalten von 230V Verbrauchern mittels GPIO funktioniert so leider nicht. Dafür ist die Leistung der GPIO-Pins nicht ausgelegt. Sie dienen vielmehr als Steuerleitungen. Du könntest entweder selber etwas basteln, um z.B. mittels eines Relais zu schalten, oder aber (und diese Lösung würde ich bevorzugen) mittels 433 MHz Sender Funksteckdosen schalten.

      Hierzu wird dann ein 433 MHz Sender (z.B. der hier: Link) am GPIO (SPI Interface Pins) angeschlossen und dieser dann z.B. über die Software Pilight gesteuert. Damit kannst Du nahezu beliebig viele Steckdosen im Haus verteilen und steuern. Als Steckdosen eignen sich dann ELRO oder Intertechnos besonders gut!

  8. Hallo,

    Ich wollte fragen, ob der zweite Befehl („sudo apt-get install gammu libgammu-i18n libgammu7 libjim0debian2 usb-modeswitch usb-modeswitch-data“) jetzt an den Surfstick gebunden ist, oder allgemein für jeden Stick funktioniert

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax