Raspberry Pi als „Audiosink“

Ich arbeite momentan an einem kleine Zoneplayer System. Während der Recherche nach geeigneter Software ist mir Airplay und UPNP AV aufgefallen. Frisch motiviert hab ich gleich etwas gebastelt um im Tanzverein dem Trainer einen Airplay Renderer anzubieten. Jetzt bin ich bei den Feinheiten.

Die Sache ist eigentlich ganz einfach wenn man weiss wie es get 😉 XBMC und damit alle XBMC-Ditributionen für das Raspberry Pi unterstützt von Haus aus Airplay und UPNP AV. Und zwar das ganze für Audio UND Video. Sehr cooles Feature muss ich sagen.

Wer Android hat, sollte sich die App BubbleUPNP mal ansehen. Die App ist kostenlos und funktioniert super. Bei Apple kann man mit Boardmitteln loslegen (Stichwor „Airplay“).

Was mich nun interessiert ist die Performance. Bedingt durch das Streaming der Daten und die Latenzen im Netz, die schwachen Prozessoren im Handy/Tablet und im Pi gibt es leider ein paar Delays. Ich versuche nun das Delay auf der Pi Seite zu minimieren und probiere deswegen jede XBMC-Distribution durch 😉

Folgende Daten konnte ich ermitteln:

Xbian:
UPNP Start / Stop: ca. 0,3s
UPNP neues Lied: ca. 5,2s
Airplay Start / Stop: ca. 3,5-4s
Airplay neues Lied: ca. 6 – 10s
Boot Dauer: ca. 47s

Raspbmc:
UPNP Start / Stop: ca. 0,4s
UPNP neues Lied: ca. 5,6s
Airplay Start / Stop: ca. 10,3s
Airplay neues Lied: ca. 11 – 15s
Boot Dauer: ca. 46s

OpenELEC:
UPNP Start / Stop: ca. 0,3s
UPNP neues Lied: ca. 6-9s
Airplay Start / Stop: ca. 3,3s (aber Aussetzer! -> zu kleiner Puffer)
Airplay neues Lied: ca. 5,5s (aber Aussetzer! -> zu kleiner Puffer)
Boot Dauer: ca. 46s

Man muss dazu sagen, dass die Liedlänge Auswirkungen auf die Zeiten hat. Desweiteren ist mein IPod Touch mit erheblich schlechterer Hardware ausgestattet als mein Android Handy. Nichts desto trotz sind die Airplay Zeiten doch etwas enttäuschend. Ich hoffe dass sich das in der Zukunft bessert. Ich denke es gibts noch etwas Tuning potienzial wenn man Puffergröße und ähnliches umstellt. Allerdings suche ich mehr eine „out of the box“ Lösung. Und hier muss man sehen das Xbian die besten Werte liefert. Ich werde das mal eine Weile beobachten 😉

Network Scanner mit dem Raspberry Pi

Heute habe ich dringend meinen alten Scanner gebraucht und musste leider feststellen, dass es keinen Windows 8 Treiber mehr gibt -.-

Abhilfe schafft da ein Raspberry Pi. Ich habe beim kauf darauf geachtet, dass der Scanner von der SANE Bibliothek unterstützt wird 🙂 Jetzt kann ich mit meinem guten alten Scanner über Netzwerk scannen.

Eine Schritt für Schritt Anleitung gibt es hier:

Raspberry Pi: Sharing a scanner with the Network – even Windows!

Alternativ kann man das Pi so einstellen, dass es über einen Knopfdruck mit dem Scan beginnt und das Bild als PDF in die Dropbox kopiert. Das ist vllt die einfachere Lösung 😀

Hier noch ein paar weitere Infos:

Scannen mit dem Raspberry Pi und Canon Scannern

Digispark

Endlich sind die Digispark eingetroffen :). Nach der Kickstarter Kampange hat nun die Auslieferung der kleinen, putzigen Arduino Boards begonnen… entschuldigung „Arduino kompatiblen“ Boards. Sie sind so gebaut, dass man sie direkt in einen USB Port stecken kann. Von dort werden sie mit Strom und Daten versorgt und können auch direkt programmiert werden. Ich bin kein großer Fan von Arduino weil ich die Sprache einfach unschön und unsauber finde, aber man kann ja auch C benutzen 😉 Die Boards an sich sind wirklich sehr klein und super preiswert. Es gibt auch eine Reihe von „Shields“, die die Funktionalität erweitern. Sobald ich etwas Zeit finde werde ich ein wenig damit herumspielen. Eine erste Idee von mir ist, die Digisparks als „Satellit“ Boards an das Raspberry Pi zu hängen und so meine Hausautomatisierung voran zu Treiben. Mal sehen ob das klappt.

Natürlich habe ich wieder zur Kamera gegriffen 😉 :

_MG_5545 _MG_5565

Infos:
http://digistump.com/#digispark

Die neue Lieferung Himbeerkuchen

Heute ist die neue Lieferung Raspberry Pi’s eingetroffen. Das neue Modell hat jetzt 512MB Ram (früher 256MB) und hat ein paar kleine Verbesserungen erhalten. So wurde auch die GPIO Schnittstelle überarbeitet und eine Reset-Funktion eingebaut. Eine Übersicht über die Neuerungen gibt es unter “ http://www.raspberrypi.org/archives/1929 „. Ich habe auf jeden Fall erstmal die Kamera gezückt 🙂

Packer Bash Script

Und hier der besagte Script aus dem letzten Post. Unter Linux wird „packer testscript.sh script.sh daten.tgz“ aufgerufen und man bekommt einen Script namens „testscript.sh“ der die datei „daten.tgz“ enthält.

#!/bin/bash
#
# Creates an script with bundled data
#
# Author: Jens Heuschkel <jens@3und20.eu>
#

BANNER="packer v0.1"

PROG=`basename "$0"`
if [ $# -ne 3 -o "$1" == "--help" -o "$1" == "-h" ]; then
  echo $BANNER
  echo "Usage: ${PROG} NEWSCRIPT SCRIPT DATA_TAR"
  echo "       Creates a wrapper called NEWSCRIPT that wraps the"
  echo "       specified SCRIPT and appends the DATA_TAR"
  echo ""
  echo "   or: ${PROG} -h|--help"
  echo "       Prints this message."
  exit 0
fi

NEWSCRIPT=$1
SCRIPT=$2
DATA_TAR=$3

echo $BANNER
echo "Checking files.."

if [ ! -e ${SCRIPT} ]
then
 echo "Script \"${SCRIPT}\" not found." >&2
 exit 1
fi

if [ ! -e ${DATA_TAR} ]
then
 echo "Data \"${DATA_TAR}\" not found." >&2
 exit 1
fi

touch $NEWSCRIPT
if [ ! -e ${NEWSCRIPT} ]
then
 echo "Can't write \"${NEWSCRIPT}\". Check rights." >&2
 exit 1
fi

# Get size
TAR_SIZE=`stat -c %s ${DATA_TAR}`

#SPLIT_CMD="tail -c ${TAR_SIZE} \$0 | tar -xz ${DATA_TAR}"
SPLIT_CMD="tail -c ${TAR_SIZE} \$0 > ${DATA_TAR}"

# Write untar part
cat > ${NEWSCRIPT} <> $NEWSCRIPT

cat >> ${NEWSCRIPT} <<'EOF' exit # Data goes here EOF cat $DATA_TAR >> $NEWSCRIPT

chmod +x $NEWSCRIPT
echo "done"
exit 0

Der Script funktioniert nach dem Vorbild von jar2sh von martiansoftware

Quelle:
http://www.martiansoftware.com/lab/jar2sh.html

More Bash

Uns schon wieder eine kleine Bash Weisheit….
Ich bastel gerade an einem Script der Scripte und Tar-Daten in eine Datei packt. Ist ganz praktisch für install Scripte die eigene Daten mitbringen sollen.

Das Ganze funktioniert so:

  • Der Script schreibt ein paar Zeilen um die Daten weg zu splitten
  • Dann wird der eigentlich Script geschrieben
  • Dann die Tar-Daten (einfach mit cat)

Beim ausführen werden die Daten einfach vom Ende weg kopiert und dann verhält sich der Script die der Ursprungsscript.

Und in dem Zusammnhang habe ich eine spielerei mit cat entdeckt:

  • cat > ZIELDATEI <<EOF schreibt die folgenden Zeilen bis EOF kommt.
  • cat > ZIELDATEI <<‚EOF‘ macht das gleiche 😀

Ich hab mich jetzt gefragt wo der unterschied ist, weil ich beides in einem Script gesehen habe.
Bei der version mit ‚EOF‘ werden Variablen nicht aufgelöst und bei EOF schon. Gut zu wissen 🙂

Java Server als Daemon auf Debian Linux

Ich habe einige Tage nach einer einfachen Möglichkeit gesucht, meine Java Programme als Daemon auf Debian Linux zu starten. Es gibt einiges an Scripten für SuSe und davon auch Portierungen auf Debian. Allerdings fand‘ ich diese Implementierungen immer unnötig kompliziert und unübersichtlich.

Gestern bin ich endlich auf eine einfache und klar programmierte Lösung gestossen. Ein einfacher Wrapperskript der alle benötigten Funktionen unterstützt. Der Skript ist von 2009 läuft aber noch einwandfrei. Allerdings ist er nicht auf Debian spezialisiert und ist für die KSH geschrieben. Ich bin mal alles durchgegangen und habe einige Anpassungen gemacht. Herausgekommen ist folgende Debian interpretation:

#! /bin/sh
### BEGIN INIT INFO
# Provides:          skeleton
# Required-Start:    $remote_fs $syslog $network
# Required-Stop:     $remote_fs $syslog $network
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Java Daemon Script
# Description:       This file should be used to construct scripts to be
#                    placed in /etc/init.d.
### END INIT INFO

# Author: Jens Heuschkel <jens@3und20.eu>

# Do NOT "set -e"

# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin

APP_NAME="MyApp"
APP_LONG_NAME="My App Server"

#the location of the pid files.
PIDDIR="/var/run"
PIDFILE="${PIDDIR}/${APP_NAME}.pid"
TIMESTAMP=$( date +%Y%m%d_%H%M%S )

#number of seconds to wait after starting up.
WAIT_AFTER_STARTUP=2

#the location of the log files
LOG_DIR="/var/log"
STDOUT="${LOG_DIR}/${APP_NAME}.stdout.log"

#PURGE_EXPRESSION="-mtime +2"
PURGE_EXPRESSION="${LOG_DIR}/${APP_NAME}*"

HEAPSIZE_INIT=16
HEAPSIZE_MAX=100
VMARGS="-Xms${HEAPSIZE_INIT}M -Xmx${HEAPSIZE_MAX}M -verbose:gc"
MAINCLASS="com.wordpress.jensheuschkel.MyApplication"
JARFILE="MyApp.jar"
ARGS=""

JAVA_COMMAND="/usr/bin/java"

# Startup with Classpath
#START_COMMAND="${JAVA_COMMAND} $VMARGS $MAINCLASS $ARGS"
# Startup with jar
START_COMMAND="${JAVA_COMMAND} $VMARGS -jar ${JARFILE} ${ARGS}"
#-----------------------------------------------------------------------------
# Do not modify anything beyond this point
#-----------------------------------------------------------------------------

checkroot() {
 if [[ $EUID -ne 0 ]]; then
  echo "This script must be run as root" 1>&2
  exit 1
 fi
}

getpid() {
  pid=""
  if [ -f "$PIDFILE" ]
  then
    if [ -r "$PIDFILE" ]
    then
      pid=`cat "$PIDFILE"|cut -d: -f1`
      host=`cat "$PIDFILE"|cut -d: -f2`
      currhost=`hostname`
      if [ "$host" != "$currhost" ]
      then
       echo "You are on the wrong host. $APP_LONG_NAME runs on $host."
       exit 1
      fi

      if [ "X$pid" != "X" ]
      then
       kill -0 $pid > /dev/null 2>&1
  if [ $? -ne 0 ]
  then
   # Process doesn't exist, so remove pidfile
   rm -f "$PIDFILE"
            echo "Removed stale pid file: $PIDFILE"
   pid=""
  fi
      fi
    else
      echo "Cannot read $PIDFILE."
      exit 1
    fi
  fi
}

#tests if the pid is alive
testpid() {
  kill -0 $pid > /dev/null 2>&1
  if [ $? -ne 0 ]
  then
   # Process is gone so remove the pid file.
 rm -f "$PIDFILE"
 pid=""
  fi
}

start() {
  echo "Starting $APP_LONG_NAME..."
  getpid
  if [ "X$pid" = "X" ]
  then
    if [ -s $STDOUT ]
    then
     #backup current file
     mv $STDOUT $STDOUT.sav.${TIMESTAMP}
    fi
    echo CLASSPATH is $CLASSPATH > $STDOUT
    echo ${START_COMMAND} >> $STDOUT
    nohup ${START_COMMAND} >> $STDOUT 2>&1 &
    echo $!:`hostname` > $PIDFILE
  else
    echo "$APP_LONG_NAME is already running."
    exit 1
  fi

  # Sleep for a few seconds to allow for intialization if required
  # then test to make sure we're still running.
  i=0
  while [ $i -lt $WAIT_AFTER_STARTUP ]
  do
    sleep 1
    i=`expr $i + 1`
  done
  if [ $WAIT_AFTER_STARTUP -gt 0 ]
  then
    getpid
    if [ "X$pid" = "X" ]
    then
      echo "WARNING: $APP_LONG_NAME may have failed to start."
      exit 1
    else
      echo "running ($pid)."
    fi
  else
    echo ""
  fi
}

stopit() {

  echo "Stopping $APP_LONG_NAME..."
  getpid
  if [ "X$pid" = "X" ]
  then
    echo "$APP_LONG_NAME was not running."
  else
    # Running so try to stop it.
    kill $pid
    if [ $? -ne 0 ]
    then
      echo "Unable to stop $APP_LONG_NAME."
      exit 1
    fi

    #  If it has not stopped in 10 tries, forcibly kill it
    savepid=$pid
    CNT=0
    TOTCNT=0
    while [ "X$pid" != "X" ]
    do
      # Show a waiting message every 5 seconds.
      if [ "$CNT" -lt "5" ]
      then
        CNT=`expr $CNT + 1`
      else
        echo "Waiting for $APP_LONG_NAME to exit..."
        CNT=0
      fi

      if [ $TOTCNT -gt 11 ]
      then
       echo "Killing by force (kill -9)"
       kill -9 $pid
      fi

      TOTCNT=`expr $TOTCNT + 1`
      sleep 1

      testpid
    done

    pid=$savepid
    testpid
    if [ "X$pid" != "X" ]
    then
      echo "Failed to stop $APP_LONG_NAME."
      exit 1
    else
      echo "Stopped $APP_LONG_NAME."
    fi
  fi
}

purge() {
#  pcmd="find $LOG_DIR -follow -type f $PURGE_EXPRESSION -print -exec rm -f {} +"
  pcmd="rm -f ${PURGE_EXPRESSION}"
  echo "Running purge: $pcmd"
  $pcmd
}

alert() {
  if [ "X$EMAIL" != "X" ]
  then
   echo "$APP_LONG_NAME is not running on `hostname`. Please check and restart." \
   | mailx -s "`hostname`: $APP_LONG_NAME is not running" "$EMAIL"
   echo "Sent alert to $EMAIL"
  fi
}

status() {
  getpid
  if [ "X$pid" = "X" ]
  then
    echo "$APP_LONG_NAME is not running."
    alert
    exit 1
  else
    echo "$APP_LONG_NAME is running (PID:$pid)."
    exit 0
  fi
}

dump() {
  echo "Dumping $APP_LONG_NAME..."
  getpid
  if [ "X$pid" = "X" ]
  then
    echo "$APP_LONG_NAME is not running."
  else
    kill -3 $pid

    if [ $? -ne 0 ]
    then
      echo "Failed to dump $APP_LONG_NAME."
      exit 1
    else
      echo "Dumped $APP_LONG_NAME."
    fi
  fi
}

####################

checkroot

case "$1" in

  'start')
    start
    ;;

  'stop')
    stopit
    ;;

  'restart')
    stopit
    start
    ;;

  'status')
    status
    ;;

  'dump')
    dump
    ;;

  'purge')
    purge
    ;;

  *)
    echo "Usage: $0 { start | stop | restart | status | dump | purge }"
    exit 1
    ;;
esac

exit 0

 

Die VM Einstellungen sind für das Rapberry Pi und sollten noch angepasst werden. Es wird auch nicht gecheckt ob JAVA installiert ist aber das kann man ja im Install-Skript des Servers machen 😉

Quelle:
http://fahdshariff.blogspot.de/2009/09/unix-wrapper-script-for-java.html

Raspberry Pi Custom Image

Mir wurde es langsam lästig, bei jeder Raspberry Pi Installation das Keyboardlayout, Timezone usw. einzustellen. Deswegen habe ich mir ein Image mit minimalen Anpassungen geschrieben. Das kann wie gewohnt auf eine SD Karte geschrieben werden (Anleitungen gibt’s auf raspberrypi.org). Nach dem ersten Start würde ich nochmal „rasp-config“ starten und „expand_rootfs“ ausführen. Folgende Einstellungen sind zu erwarten:

  • Location: de_DE.UTF-8
  • Keyboardlayout: Generic 105-Key German
  • Timezone: Europe/Berlin
  • Memory-Split: 240MB für ARM
  • Vorinstallirte Programme: watchdog, vim, htop, cpufrequtils, opendk-7-jre
  • watchdog aktiviert
  • .bashrc für root
  • .vimrc für pi und root
  • sshd Port auf 2224 gesetzt

Und hier der Downloadlink:
2012-09-18-wheezy-raspbian-custom.zip

Image

Raspberry Pi shutter switching shield

ich habe mal mein Hausbus Schaltplan zum Ansteuern von Rolläden überarbeitet. Anstatt eines AVR kommt hier das Raspberry Pi zum Einsatz und wird über die GPIO Schnittstelle angesteuert. Zusätzlich sind einige optionalen Features mit auf dem Board: Anschlüsse für I2C (inkl. Pullups) und UART, ein CAN Modul und 3 Status-LEDs. Damit können sehr leicht weitere Sensoren oder Boards angeschlossen werden. Eine zusätzlichen Anschluss für eine Stromversorgung gibts auch, da über den 5V Anschluss nur ca. 300 mA zu erwarten sind. Der wird insbesondere dann gebraucht, wenn man das CAN Modul mit drauf nimmt. Der Anschluss hat mit 4 Adern einen integrierten Stromversorgunsanschluss. Auf diesem soll 12V anliegen. Um die 12V zu erreichen wird ein StepUp Regler eingebaut (integriertes Modul von Reichelt mit 70% Effizienz).

In den kommenden Tagen gibt’s noch ein Board und eine Stückliste dazu. Das Ganze ist so gestaltet, dass das Pi direkt auf das Board montiert werden kann, und so Platzsparend untergebracht werden kann.

Mein Ziel ist es damit eine billige und flexible Lösung zur Automatisierung zu bauen.

Download als PDF:
shutter_device_pi schaltplan

Make the Raspberry Pi wireless (mit dem MicroNEXT USB Stick)

Heute mal eine kleine Anleitung zum Thema WLAN mit dem Raspberry Pi.
Farnell bietet den MicroNEXT USB WLAN-Stick als Zubehör an. Auf dem Stick ist genau wie auf dem populären Edimax EW-7811UN Stick ein RTL8188CUS Chip verbaut.Herausfinden kann man das über den Befehl:

pi@raspberrypi ~ $ sudo lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp.
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp.
Bus 001 Device 004: ID 046d:c52b Logitech, Inc. Unifying Receiver
Bus 001 Device 005: ID 0bda:8176 Realtek Semiconductor Corp. RTL8188CUS 802.11n WLAN Adapter

Der Befehl listet alle USB-Geräte auf. In diesem Fall sieht man, dass der WLAN Stick und ein Logitech Empfänger angeschlossen ist 😉

Die Installation der WLAN Sticks mit diesem Chipsatz ist extrem einfach geworden. In der Community gibt es einen Script, der die ganze Arbeit übernimmt. Folgende einfache Schritte sind für die Installation nötig:

  1. Stick aus dem USB Slot ziehen!
  2. In den Ordner „boot“ navigieren:
    pi@raspberrypi ~ $ cd /boot/
  3. Den Script herunterladen:
    pi@raspberrypi /boot $ sudo wget http://dl.dropbox.com/u/80256631/install-rtl8188cus-latest.sh
  4. Den Script ausführbar machen:
    pi@raspberrypi /boot $ sudo chmod +x install-rtl8188cus-latest.sh
  5. Den Script als root ausführen und den Anweisungen folgen:
    pi@raspberrypi /boot $ sudo ./install-rtl8188cus-latest.sh
  6. Der Script fordert dich irgendwann auf, den Stick einzustecken. Dem sollte man auch erst zu dem Zeitpunkt folge leisten. Nach einer kurzen Wartezeit kann man „Enter“ drücken und das Pi wird sich mit dem WLAN verbinden.

Bei mir beendet sich der Script am Ende nicht richtig. Nach ein paar Minuten Wartezeit habe ich ihn mit „STRG+C“ beendet. Seit dem funktioniert das WLAN wunderbar. Übrigens scheint das Raspberry Pi genug Strom für den Stick zu liefern. Also war bei mir kein externer Hub nötig.

Raspberry Pi mit WLAN Stick

Quellen:
Forums Thread (Englisch): http://www.raspberrypi.org/phpBB3/viewtopic.php?t=10360&p=127674
Script: http://dl.dropbox.com/u/80256631/install-rtl8188cus-latest.sh