Webcam Technik

Zu der Technik der Webcam.

Irgendwie wollte ich so was schon immer einmal machen. Nur was soll man da zeigen? Den Himmel, die Straße, den Garten? Überall die Gefahr das man jemanden mit aufnimmt dessen Persönlichkeitsrecht man dabei verletzt. Da kam mir das Projekt von Anja wie gerufen. :-) Die Garnelen werden sich nicht beschweren – will ich doch hoffen. :-D

Links seht ihr (wenn ihr keinen Adblocker (Werbefilter) aktiv habt) welche Webcam ich mir dafür ausgesucht habe. Gut fand ich an ihr, dass sie recht viele Möglichkeiten (Upload per FTP, HTTP (HTTP-PUT – nicht zu empfehlen ohne Webdav), eMail und Stream) bietet, das Bild zu veröffentlichen. Die Trigger kann man entweder durch Bewegung, einem externen Sensor oder einen Timer steuern. Ich habe einen Timer von 1 Minute gewählt der für den Zeitraum, in dem auch Licht im Cube eingeschaltet ist, läuft. Die so aufgenommenen Bilder werden per FTP auf einen FTP-Server geladen. Leider kann die Kamera kein SSL (FTPS), weshalb ich nicht direkt auf die Blog-Seite gehe. Der Weg ist so zwar etwas komplizierter aber ich möchte keine unnötigen unverschlüsselten Verbindungen zu dem Server zulassen. Daher lege ich die Bilder der Webcam auf einen offenen FTP-Server auf dem sonst auch nichts weiter liegt als das Bild. Von dort hole ich mir dann das Bild per SCP auf den Server, auf dem das Blog installiert ist. Da die Webcam immer zur vollen Minute ein Bild auf den FTP-Server lädt, hole ich es immer 10 Sekunden später wieder ab.

Um nun die Bilder auf der Seite automatisch neu zu laden, habe ich mir erst überlegt, mein Lieblings JavaScript-Framework “jQuery” zu verwenden, mich dann aber dagegen entschieden. Zum einen wollte ich selber mal wieder mit dem DOM herum basteln und zum anderen muss man ja auch kein riesiges Framework mit schleppen, wenn es nur um 2-3 Funktionen daraus geht.

Hier also noch das Script für das aktualisieren des Bildes (rechts scrollen):

var timer1, timer2, timer3;
var errorcount=0;
var ReloadTimeout=60;
var HideTimeout=3;
var OnlineText  = '.... Bild wird aktualisiert ....';
var OfflineText = 'Das Licht im Cube ist gerade aus, daher findet keine Aktualisierung statt.';
var WebCamImage = document.images['WebCamGarnelen'];

var debug = 0;
var debugwindow;

var iebody    = (document.compatMode && document.compatMode!="BackCompat")? document.documentElement : document.body;
var docwidth  = (window.innerWidth)  ? window.innerWidth  : iebody.clientWidth;
var docheight = (window.innerHeight) ? window.innerHeight : iebody.clientHeight;

function compare_to_now(mytime) {
  //  1 = Uebergebene Zeit ist groesser als aktuelle Zeit
  //  0 = Zeiten sind gleich
  // -1 = Uebergebene Zeit ist kleiner als aktuelle Zeit

  var jetzt = new Date();
  var tocomp = new Date(jetzt.getFullYear(), jetzt.getMonth(), jetzt.getDate(), mytime.substr(0,2), mytime.substr(3,2), 0 );

  if (jetzt > tocomp)
  	return -1;
  if (jetzt < tocomp)
  	return 1;

  return 0;
}

function writelog(txt){
	if(typeof window.console != 'undefined'
    && typeof window.console.log != 'undefined'){
		console.log('webcam.js:' + txt);
	} else if ( debug == 1 ) {
		if (!debugwindow) {
			debugwindow = window.open('', "Debug", "left="+(docwidth / 2)+",top="+(docheight/2)+",scrollbars=yes,resizable=yes");
			debugwindow.document.open();
			debugwindow.document.write('<html>n<head>n<title>Debug</title>n</head>n<body>n<h3>Debugausgaben</h3>n');
		}
		debugwindow.document.write('webcam.js:' + txt + "<br /><br />n");
		debugwindow.scrollTo(0,debugwindow.innerHeight);
		debugwindow.focus();
	}
}

function showLoadImage(TextToShow) {
	var LoadText = document.getElementById('CamLoadInfo');
	writelog('show the loadinfo....');
	LoadText.firstChild.nodeValue = TextToShow;
	writelog('text is set to: ' + LoadText.firstChild.nodeValue);
	LoadText.setAttribute('style', 'visibility:visible;color:red;text-align:center;');
	writelog('style-attribute of ' + LoadText.getAttribute('id') + ' is set to: ' + LoadText.getAttribute('style'));
}

function hideLoadImage() {
	var LoadText = document.getElementById('CamLoadInfo');
	writelog('hide the loadinfo....');
	LoadText.setAttribute('style', 'visibility:hidden;color:red;text-align:center;');
	writelog('style-attribute of ' + LoadText.getAttribute('id') + ' is set to: ' + LoadText.getAttribute('style'));
	clearTimeout(timer3);
}

function checkImage()
  {
    writelog('checkImage called ' + ++errorcount + ' times');
    if (!WebCamImage.complete) {
      timer1 = setTimeout('checkImage()', 1000);
      if (errorcount > 30){
        writelog('page must be reloaded.....');
        window.location.reload();
      }
      return 0;
    } else {
      clearTimeout(timer1);
      writelog('set hiding timer to '+HideTimeout+' sec.');
      timer3 = setTimeout('hideLoadImage()', 1000 * HideTimeout);
   }
  } 

function reloadImage(){
  writelog('reloadImage called');
  // Reload nur wenn in der onlinezeit
  clearTimeout(timer2);
  if ( (compare_to_now('07:00') <= 0 && compare_to_now('12:00') > 0 )
    || (compare_to_now('15:00') <= 0 && compare_to_now('20:00') > 0 )
    || (compare_to_now('21:30') <= 0 && compare_to_now('22:30') > 0 ) ){
    writelog(new Date() + ' in online time, set new image');
    showLoadImage(OnlineText);
    WebCamImage.src=WebCamImage.src.substring(0, WebCamImage.src.indexOf('?')) + '?' + Math.ceil(Math.random() * 1000000);
    writelog('new image name: '+ WebCamImage.src);
    errorcount=0;
    writelog('call checkImage in 1 sec');
    timer1 = setTimeout('checkImage()', 1000);
  } else {
    writelog(new Date() + ' in offline time, nothing to do - save server requests');
    showLoadImage(OfflineText);
  }
  writelog('set reload timer to '+ReloadTimeout+' sec.');
  timer2 = setTimeout('reloadImage()', 1000 * ReloadTimeout);
}

reloadImage();

Was passiert?
Die Funktion “reloadImage”, die gleich als erstes aufgerufen wird, prüft ob der Aufruf im “Online-Zeitfenster” der Webcam ist.
Sollte das der Fall sein, wird der Lade-Text gesetzt und sichtbar gemacht (Funktion showLoadImage).
Danach wird die src-Adresse des Bildes neu gesetzt. Da das Bild aber den selben Namen hat, gibt es noch eine Zufallszahl als Requestparameter hinter das Bild, um ein Reload zu “erzwingen” bzw. den Browsercache “auszutricksen”.

Nun wird ein Timer gesetzt, der nach einer Sekunde die Funktion “checkImage” aufruft. Diese Funktion prüft, ob das Bild erfolgreich geladen wurde oder ein Fehler passiert ist.
Sollte das Bild unvollständig oder fehlerhaft geladen sein, so ruft sich “checkImage” im Sekundenintervall bis zu 30 Mal wieder auf. Führt das auch zu keinem Erfolg, wird die komplette Seite einmal neu geladen.
Wurde das Bild erfolgreich geladen, wird der timer von “checkImage” gelöscht und nach einem timeout der Lade-Text durch die Funktion “hideLoadImage” wieder versteckt.

Befinden wir uns nicht in dem “Online-Zeitfenster” wird der Text über “showLoadImage” mit einer Info über die Online-Zeiten gesetzt und dauerhaft angezeigt.

Am Ende wird noch ein Timer gesetzt, der die Hauptfunktion “reloadImage” nach 60 Sekunden erneut aufruft.

Außerdem schreibt das Script auf die Konsole des Browsers, wenn es eine vorfindet (FireBug, Web-Konsole im Firefox oder die Konsole von Google-Chrome). Wird der debug-schalter auf 1 gesetzt und es gibt kein Plugin oder Konsolenuntersützung vom Browser (z.B. IE) wird ein Debugfenster geöffnet in das die Konsolenausgabe geschrieben wird.

Der Teil auf der Webseite um das ganze zu “aktivieren” (rechts scrollen):

<img class="aligncenter" src="{PATH_ANPASSEN}/webcam.jpg?0" alt="WebCam" name="WebCamGarnelen" width="640" height="480" />
<div id="CamLoadInfo" style="visibility:hidden;color:red;text-align:center;">.... Bild wird aktualisiert ....</div>

<noscript><div style="color:red;">Bitte aktivieren Sie JavaScript in ihrem Browser, damit das Bild automatisch aktualisiert werden kann. Wenn Sie das nicht möchten, müssen Sie die Seite manuell von Zeit zu Zeit neu laden.</div></noscript>
<script type="text/javascript" src="{PATH_ANPASSEN}/webcam.js"></script>

Hier geht es nur darum die im JavaScript angesprochenen DOM-Elemente auf der Seite zu haben und den eigentlichen JavaScript zu laden. Sollte JavaScript deaktiviert sein, wird ein alternativer Text ausgegeben.

Hier sind die Kommentare offen für Fragen oder Anregungen – Danke, Alex.

Hinterlasse eine Antwort

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

*

Du kannst folgende HTML-Tags benutzen: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

eMail-Benachrichtigung bei weiteren Kommentaren.
Auch möglich: Abo ohne Kommentar.