Bandbreitenbegrenzung in Richtung Mobotix Kamera
Hintergrundinfo
Eine Bildauflösung von 640×480 Bildpunkten benötigt pro Sendeaktion eine Bandbreite von ca. 307kBit. Werden nun von einem oder mehreren Usern Bilder der Webcam abgerufen, so kann dieses sehr schnell größere Datenmengen mit sich bringen, die sich bei Nutzung von aDSL sehr schnell negativ auf die vorhandene Upstreambandbreite auswirken. Besonders kritisch wäre dies noch dazu, wenn der böswillige Nutzer die Frameraten selbst einstellt.
Abhilfe kann hier zum Beispiel leisten, die Bilddaten nicht für das WWW, vom Webserver der „kleinen Kamera“ abzufackeln, sondern von einem Webserver, der eine entsprechend „dicke“ Upstreamleitung zum Internet besitzt. Freilich könnte man nun die Bilder von der Kamera via FTP auf einen Webserver schieben, dies ginge recht gut bei Standbildern - bei Echtzeitkommunikation wird es hier auch schon schwerer. Ganz zu schweigen von der andauernden Übertragung von Nutzer-/Logindaten beim Upload.
Unter Umständen, wie auch in der Konfigurationsumgebung im SOHO-LAN, steht auf dem Webserver gar kein FTP-Server zur Verfügung. Wir müssen also dies anders und auch eleganter lösen.
Lösung
Wir cashen den Traffic über einen zentralen Proxy, holen uns von dort die Kamerabilder direkt von der Mobotix-Kamera und gestatten über diesen Proxy den Zugriff für das gemeine Fußvolk.
Hierzu sind ein paar Vorarbeiten auszuführen.
RAM-DISK
Damit nun unser Caching nicht auf Lasten der Festplatten-Stapel geht (Datendurchsatz und Schreib-/Lesezugriffe) nutzen wir für unseren VHost eine RamDisk.
Diese legen wir wie folgt an:
# vim /etc/fstab
/dev/shm /var/www/html/webcam tmpfs defaults,size=3m,mode=750,uid=69,gid=69 0 0
Die User- und Group-ID stellen wir dann auf den/die User/Gruppe apache ein.
Anschließend mounten wir unsere zusätzliche RAM-Disk:
# mount /var/www/html/webcam
Da wir sowohl über das Verzeichnis record wie auch current unsere Bilder bzw. Liveimages weitergeben wollen, legen wir diese beiden Verzeichnisse an:
# mkdir /var/www/html/webcam/control/
# mkdir /var/www/html/webcam/record/
Anschließend passen wir noch die betreffenden Userrechte an:
# chown apache:apache /var/www/html/webcam/control/
# chown apache:apache /var/www/html/webcam/record/
DokumentRoot-Erweiterungen
Für unsere Webcam(s) legen wir nun einen VHost an:
# vim /etc/httpd/conf.d/vhosts.conf
- vhosts.conf
# # webcam.nausch.org # <VirtualHost *:80> ServerAdmin webmaster@nausch.org ServerName webcam.nausch.org:80 ServerAlias webcam.nausch.org *.webcam.nausch.org ServerPath / DocumentRoot "/var/www/html/webcam" <Directory "/var/www/html/webcam"> Options FollowSymLinks AllowOverride None Order allow,deny Allow from all </Directory> DirectoryIndex index.html index.php ErrorLog logs/webcam_error.log CustomLog logs/webcam_access.log combined </VirtualHost>
Nach einem Restart unseres Apache-Webservers steht uns nun dieser VHost zur Verfügung.
Webseite an-/festlegen
Unseren Gastzugang lehnen wir dann an den originalen Zugang dere Mobotix-Kameras an. Von unserem Root-Server mit der fetten Internetanbindung lassen wir dann alle 5 Sekunden die Wettercam-Bilder automatisch nachladen.
Das ganze soll dann wie folgt aussehen:
Initiale Bildbefüllung
Für einen ersten Test holen wir uns jeweils ein aktuelles Webcambild und speichern dieses unter cd /var/www/html/webcam/record/ ab.
# cd /var/www/html/webcam/record/ # wget http://192.168.100.101/record/current.jpg # mv current.jpg current_2.jpg # wget http://192.168.100.100/record/current.jpg # cp /var/www/html/webcam/record/current.jpg /var/www/html/webcam/control/cam1.jpg # cp /var/www/html/webcam/record/current.jpg /var/www/html/webcam/control/cam2.jpg
HTML-Seite anlegen
Damit in der Überschrift die aktuellen Daten der Wetterstation eingefügt werden, nutzen wir die automatische Seitengenerierung durch software_-_wview. Wie legen uns also im Arbeitsverzeichnis von Wview ein Grundgerüst unserer HTML-Seite an.
# vim /usr/local/etc/wview/html/webcam.htx
- webcam.htx
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>Private Wetterstation Pliening in Bayern</title> </head> <script language="JavaScript"> function openURL(urlname) { window.location=urlname; } </script> <body style="background-image: url(django_bg.jpg);"> <!-- nav-buttons_Plus.incx --> <table align="center" border="0" cellpadding=2 cellspacing=2> <tr> <td colspan="5" align="center" valign="top" height="30"> <input type="button" value=" Übersicht " onclick="openURL('https://wetter.nausch.org/index.html')"> <input type="button" value=" Almanach " onClick="openURL('https://wetter.nausch.org/Almanac_Plus.htm')"> <input type="button" value=" aktuelle Werte " onClick="openURL('https://wetter.nausch.org/Current_Plus.htm')"> <input type="button" value=" Letzte 24 Std. " onClick="openURL('https://wetter.nausch.org/Daily_Plus.htm')"> <input type="button" value=" Letzte 7 Tage " onClick="openURL('https://wetter.nausch.org/Weekly_Plus.htm')"> <input type="button" value=" Letzte 28 Tage " onClick="openURL('https://wetter.nausch.org/Monthly_Plus.htm')"> <input type="button" value=" Letzte 365 Tage " onClick="openURL('https://wetter.nausch.org/Yearly_Plus.htm')"> <input type="button" value=" Stationsdaten " onClick="openURL('https://wetter.nausch.org/Station.htm')"> <input type="button" value=" akt. Blitzkarte " onClick="openURL('https://wetter.nausch.org/stormforce.htm')"> <input type="button" value=" Impressum " onClick="openURL('https://wetter.nausch.org/Impressum.htm')"> </td> </tr> </table> <!--include header.inc--> <!-- Aufforderung zum Aktivieren von JavaScript --> <noscript> <center> <p> <a href="https://webcam.nausch.org/control/userimage.html"><font face="Helvetica,Arial" size="-1">Open Menu (cam1)</font></a> </p> <p> <font face="Helvetica,Arial" size="+3" color=red>Press Shift-Reload to refresh the image.<br>Enable JavaScript / Active Scripting to see more details.</font> </p> </center> </noscript> <!-- Seitenkorpus --> <hr> <font size="4" face="Arial, Helvetica, sans-serif" color="#000000">Wetterwebcams der Wetterstation</font> <br> <table cellpadding="2" cellspacing="0" border="0" width="100%" align="center"> <tbody> <tr> <td> Kamera mit Blickrichtung Westen (München)<br> <font size="1" face="Arial, Helvetica, sans-serif" color="#000000"> </font> </td> <td> Kamera mit Blickrichtung Osten (Markt Schwaben)<br> <font size="1" face="Arial, Helvetica, sans-serif" color="#000000">(temporär 'gen Norden bis Außenmontage möglich)</font> </td> </tr> <br> <tr> <td> <img src="https://webcam.nausch.org/control/cam1.jpg" width="620" height="465" name="camimage1" alt="Kamera-Livebild - Aktualisierung einmal pro Minute"> </td> <td> <img src="https://webcam.nausch.org/control/cam2.jpg" width="620" height="465" name="camimage2" alt="Kamera-Livebild - Aktualisierung einmal pro Minute"> </td> </tr> <tr> <td> <a href="https://webcam.nausch.org/index.html"><font face="Helvetica,Arial" size="-1">Open Menu (cam1)</font></a> </td> <td> <a href="https://webcam.nausch.org/index.html"><font face="Helvetica,Arial" size="-1">Open Menu (cam2)</font></a> </td> </tr> </tbody> </table> <hr width="100%" size="4"> <table cellpadding="2" cellspacing="2" border="0" width="100%"> <tbody> <tr> <td width="40%" valign="bottom" align="left"> <small> <font face="Arial, Helvetica, sans-serif" align="left" color="blue"> <a href="https://wetter.nausch.org">wetter.nausch.org</a> </font> </small> </td> <td width="20%" valign="bottom" align="center"> <small> <font face="Arial, Helvetica, sans-serif" align="center" color="blue"> . </font> </small> </td> <td width="40%" valign="bottom" align="right"> <small> <font face="Arial, Helvetica, sans-serif" align="right" color="blue"> <a href="https://wetterstation-pliening.info">wetterstation-pliening.info</a> </font> </small> </td> </tr> </tbody> </table> <script language="JavaScript"> var imageUrl1=document.camimage1.src; var imageUrl2=document.camimage2.src; var random=new Date().getTime(); var delay=1; // Aktualisierung in Sekunden var counter=0; var buffer1=new Image; var buffer2=new Image; function DisplayImage1() { document.camimage1.src=buffer1.src; LoadNextImage(); } function DisplayImage2() { document.camimage2.src=buffer2.src; LoadNextImage(); } function LoadBuffer () { var trickname1=imageUrl1; var trickname2=imageUrl2; ++counter; trickname1+="?counter="+(random+counter); trickname2+="?counter="+(random+counter); buffer1.src=trickname1; buffer1.onload=DisplayImage1; buffer2.src=trickname2; buffer2.onload=DisplayImage2; } function LoadNextImage () { setTimeout("LoadBuffer()", 1000*delay); // Millisekunden*1000 -> Sekunden } LoadNextImage(); </script> </body> <html>
Da wir die, von wview generierte HTML-seite als index.HTML für unseren VHOST verwenden wollen, lassen wir die generierte Seite von Wview noch an die richtige stelle kopieren.
# cat /usr/local/etc/wview/post-generate.sh
- post-generate.sh
#/bin/sh # Add any post template generation processing or utilities here. Keep in mind this # script runs in the htmlgend process's context so don't add anything that is overly # time constrained. /bin/cp /usr/share/wview/webcam.htm /var/www/html/webcam/index.html /bin/cp /usr/share/wview/webcam.htm /var/www/html/webcam/control/userimage.html
Bild-Caching
Updatescript
Da wir natürlich immer auf das gerade aktuelle Kamerabild zugreifen wollen, müssen wir nun noch dafür sorgen, dass die Bilder auch fortlaufend gecached werden.
Hierzu behelfen wir uns eines kleinen Bash-Scriptes.
# vim /usr/local/bin/camcash.sh
- camcash.sh
#!/bin/sh # Script zum Abholen und Abspeichern der Kamerabilder # für den virtuellen Mobotix-Cambetrieb # (c) Michael Nausch - 29.12.2008 WORKDIR_1="/var/www/html/webcam/control/" WORKDIR_2="/var/www/html/webcam/record/" CAMURL_1="http://192.168.100.100/record/current.jpg" CAMURL_2="http://192.168.100.101/record/current.jpg" SLEEP=1 cd $WORKDIR_1 while true do wget $CAMURL_1 rsync $WORKDIR_1"current.jpg" $WORKDIR_2"current.jpg" rsync -av current.jpg cam1.jpg rm current.jpg wget $CAMURL_2 rsync $WORKDIR_1"current.jpg" $WORKDIR_2"current_2.jpg" rsync -av current.jpg cam2.jpg rm current.jpg # sleep $SLEEP done
Über die Variable $SLEEP legen wir den Refreshzyclus fest, also einfach auskommentieren und den Verzögerungsfaktor festlegen.
Automatischer Start bei Systemstart
Damit nun nach einem Systemstart der Bildercashvorgang automatisch anläuft legen wir uns ein passendes Startscript an:
# vim /etc/init.d/weathercam
- weathercam
#!/bin/sh # # chkconfig: 2345 79 31 # description: cyclic Weatherwebcam-Picture Update # # processname: weathercam # # Source function library. . /etc/rc.d/init.d/functions # Source networking configuration. . /etc/sysconfig/network # Check that networking is up. [ ${NETWORKING} = "no" ] && exit 0 prog=cam2pic.sh cam_prg=/usr/local/bin/$prog # Source an auxiliary options file if we have one, and pick up OPTIONS, if [ -r /etc/sysconfig/$prog ]; then . /etc/sysconfig/$prog fi start() { echo -n $"Starting $prog: " $cam_prg & RETVAL=$? echo [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog } stop() { echo -n $"Stopping $prog: " /usr/bin/killall $prog RETVAL=$? echo [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog } restart() { stop start } # See how we were called. case "$1" in start) start ;; stop) stop ;; restart) restart ;; *) echo $"Usage: $0 {start|stop|restart|}" exit 1 esac exit $RETVAL
Die Ausführungsrechte geben wir dann unserem script mittels:
# chmod +x /etc/init.d/weathercam
Damit der „service“ automatisch beim Systemstart anläuft, aktivieren wir diesen mit:
# chkconfig weathercam on
Die Überprüfung ob der Dienst (Daemon) stormforce wirklich bei jedem Systemstart automatisch mit gestartet werden, kann durch folgenden Befehle erreicht werden:
# chkconfig --list | grep weathercam
weathercam 0:Aus 1:Aus 2:Ein 3:Ein 4:Ein 5:Ein 6:Aus Den Daemon starten wir nun initial mit:
# service weathercam start
Zur Sicherheit sichern wir uns den Inhalt unseres VHostes/Ramdisk noch, damit wir diesen ggf. später zurückspielen können:
# tar cfvj /root/webcam_backup_090104.tar.bz2 /var/www/html/webcam tar: Removing leading `/' from member names /var/www/html/webcam/ /var/www/html/webcam/cgi-bin/ /var/www/html/webcam/cgi-bin/guestimage.html /var/www/html/webcam/control/ /var/www/html/webcam/control/cam2.jpg /var/www/html/webcam/control/cam1.jpg /var/www/html/webcam/control/userimage.html /var/www/html/webcam/record/ /var/www/html/webcam/record/current_2.jpg /var/www/html/webcam/record/current.jpg /var/www/html/webcam/record/stormforce_2.png /var/www/html/webcam/record/stormforce.png /var/www/html/webcam/record/current2.jpg /var/www/html/webcam/index_old.html /var/www/html/webcam/faviconx.ico /var/www/html/webcam/favicon.ico /var/www/html/webcam/django_bg.jpg /var/www/html/webcam/current/ /var/www/html/webcam/current/cam2.jpg /var/www/html/webcam/current/cam1.jpg /var/www/html/webcam/index.html