Hallo zusammen,
da ich bereits zwei günstige Webcams hatte, beide mit Motion Detection und Benachrichtigung per Mail und/oder per FTP Upload habe ich mir mal ein paar Gedanken gemacht, wie man diese ‚Events‘ an IP-Symcon bekommt und von dort aus Aktionen steuern kann.
Herausgekommen ist folgende Lösung, die seit 4 Tagen zuverlässig läuft und gänzlich konfigurierbar ist:
[ol]
[li]Günstige WLAN Webcams für ca 45 EUR[/li][li]JAVA SMTP Bridge Server (eigenprogrammiert, s.u.)[/li][li]IPS PHP Script mit Alarm, und Email Funktion[/li][/ol]
1. WebCAMS
Die Wlan Webcam werden ganz normal in Betrieb genommen und Motion Detection aktiviert.
Es funktioniert tadellos mit günstigen WebCams zb. von DLINK oder EdiMax.
Wichtig ist nur, dass diese Mails versenden können bei Bewegung.
2. JAVA SMTPBridge
Auf dem IPS Server wird ein kleines JAVA Programm als Dienst eingerichtet, das eine Art SMTP Server läuft.
Dieses Programm nimmt die Mails von den Webcams entgegen und ordnet diese anhand der Absender und Ziel-Adresse einer bestimmten Aktion zu.
Die SMTPBridge kann komplett über ein config.xml konfiguriert werden.
Es werden folgende Triggeraktionen unterstützt:
[ul]
[li]Nachricht senden an einen Rechner (host, port)[/li][li]ein beliebiges Kommando mit exec ausführen[/li][/ul]
3. IPS Script
In IP-Symcon habe ich einen Server Socket mit einer Registervariablen eingerichet, der die Nachricht von der SMTPBridge empfängt und an ein Script weiterleitet.
Das Script kann derzeit folgendes:
[ul]
[li]Bei Trigger durch SMTPBridge wird von der Webcam das aktuelle Bild geladen und im Media Folder gespeichert.[/li][li]Zusätzlich wird das Bild in einem History Ordner gespeichert (Aufbewahrungsanzahl konfigurierbar).[/li][li]Falls gewünscht erstellt das Script eine Variable die gesetzt und wieder zurückgesetzt wird, wenn eine Bewegungsnachricht eintrifft.[/li][li]Nun wird bei Bedarf noch eine Email verschickt mit Anhang.[/li][li]Script ist tauglich für beliebig viele WebCams[/li][/ul]
Funktioniert bei dir die Bewegungserkennung im Außenbereich zuverlässig?
Ich habe die Erfahrung gemacht, das da bei Helligkeitsschwankung zuviele Fehlmeldung kommen…
Also ich kann mich bisher nicht beklagen.
Die Bilder an der Eingangstür sind eigentlich perfekt. dh. keine fremden Ereignisse. habe aber hier die motion detection nur auf bestimmte Bereiche des Bildes aktiviert und auch die Empfindlichkeit runtergestellt. Hier setze ich eine DLink ein - hinter dem Fenster - Abends habe ich hier halt ein Problem mit Reflexen im Fenster - sonst aber gut.
Dh. Wolken oder auch Wind wird hier ignoriert.
Bisher hatte ich wirklich nur Personen auf den Bildern und auch mal eine Katze
Auf der Terrasse habe ich eine etwas ältere billig Edimax auch um die 50 EUR.
Hier ist die Konfiguration noch nicht ganz so schön und die Parameter sind nicht ganz einfach einzustellen.
Allerdings taste ich mich hier auch grad ran und es wird besser.
So, endlich komme ich dazu eine grobe Anleitung zu schreiben:
ZIP Anbei entpacken in einen Ordner - Zb. IP-Symcon\User\SMTPBridge
Config.XML Datei korrekt(!) pflegen.
Pro Kamere ein trigger eintrag mit korrekter ID etc. From / To korrekt ausfüllen (muss überinstimmen mit SMTP Einstellungen der jew. WEBCAM)
So wird die Zuordnung korrekt gemacht bei mehreren Webcams. Type gibt was und wie getriggert werden soll. hier sock angeben
(alternativ kann man exec eintragen dann wird irgend ein befehl abgesetzt.) Host und Port noch den hostnamen und den Port von IPS angeben auf dem gehorcht wird. command ist entweder der befehl der ausgeführt wird mit exec oder der command der an den port gesendet wird.
Starten kann man das Programm mit:
„C:\Program Files (x86)\Java\jre7\bin\java.exe“ SMTPBridge
Java muss installiert sein.
Jetzt kann man mal mails an die SMTP Bridge senden (Firewall ggf. öffnen!) und sollte was sehen.
Wer will kann das Programm noch als Dienst installieren, damit es immer mit windows startet.
.reg file ausführen und ggf. drin die pfade vorher anpassen.
Nun sollte die SMTP Bridge erstmal laufen. IN IPS ist nun folgendes notwendig:
[li]Wir legen eine I/O Instanz an Einen ServerSocket
[/li][li]Als Port geben wir an 6901 (oder entsprechend der Configuration in der XML)
[/li][li]Nun legen wir eine RegisterVariable an und geben als Übergeordnete Instanz den gerade erstellten WebserverSocket an
[/li][li]und als Ziel ID ein vorher angelegtes Script das die Befehle auswertet
[/li]Hier mal ein Beispiel für mein Script:
php // Reciever for Socket Information $cam = explode(":",trim($_IPS['VALUE']))[1]; // Hier wird die info von der SMTPBridge ausgewertet da die SMTPBridge // sendet SMTPTRIGGER:%from% also SMTPTRIGGER:WEBCAM1 steht in $cam WEBCAM1 // nun standard Script aufrufen und ID der Webcam übergeben IPS_RunScriptEx(22652 /*[Scripts\Internet Scripts\WebCam\WebCam Image Trigger]*/,Array("CAMID
Das zweite Script kann dann div. Dinge tun.
ich poste hier mal mein generelles Script hier:
Das Script benötig die settings klasse (siehe hier:)
<?
/* Webcam Trigger Script ----------------------------------------------------
Script das Webcam Events auffängt (motion Detection) und dann bestimmte
aktionen durchführt. Script ist nutzbar für viele Webcams.
Das Script kann folgendes:
- Event empfangen (zb. über Port Trigger), dann für die gegebene WebCam
die Aktion durchführen
- Eingeplant als periodisches Ereignis - lädt Bilder aller konfigurierten
Webcams
- Speichert Bilder im Media Folder und verkleinerte Bilder im Archiv
- Sendet Mails - konfigurierbar (einaml, dauerhaft, aus)
Konfiguration:
die WebCams werden im Array $cams hinterlegt.
Jede Cam benötigt ein Identifier zb. $cams["MEINE_CAM1"].
Danach werden folgende Parameter gestzt:
title : Titel der WebCam wird zb. auch ins Bild mit Uhrzeit geschrieben
url: Die URL zur Kamera wo das LiveBild (Einzelbild) abgeholt wird
user: Basic Authentication User der CAM
pwd: Basic Authentication Kennwort der CAM
textposY: Legt fest, wo der Titel und die Uhrzeit Vertikal im Bild
platziert werden (Pixel)
trigger_var: Wenn gesetzt, wird eine Triggervariable für die Webcam erzeugt,
diese wird auf TRUE gesetzt, wenn Bewegung erkannt wird.
history: Anzahl der Bilder, die ins Archiv gehen - älteste werden Gelöscht.
email: Instanz des IPS SMTP Sender Moduls, falls <> 0, dann wird eine
Kategorie mit Variable zur Webcam angelet, mit der eingestellt
werden kann, ob man per Mail benachrichtigt werden soll, wenn
Motion erkannt wird.
Generelle Konfig Parameter:
$c_font: Schrit die verwendet wird um in das Bild zu schreiben
$c_minpause: Minimale Wartezeit, bevor das Script wieder anläuft
(verhindert viele Bilder / Mails etc. bei viel Bewegung)
$c_motionTimeout: Nach dieser Zeit wird die TriggerVariable
(Bewegungserkennung wieder auf false gesetzt, wenn keine
neue Bewegung mehr erkannt wurde).
$c_historyPath: Pfad zum Archiv (sollte gelassen werden wg. Zugriff vom
Webfront)
$c_mail_subject: Beginn des Betreffs der Email bei Bewegungserkennung
//--------------------------------------------------------------------------*/
$cams["webcam_1"]["title"] = "WebCam Balkon";
$cams["webcam_1"]["url"] = "http://192.168.178.70:4000/jpg/image.jpg";
$cams["webcam_1"]["user"] = "admin"; // Basich Auth User
$cams["webcam_1"]["pwd"] = "123"; // Basic Auth Password
$cams["webcam_1"]["textposY"] = 450; // Y Vertical position of text on image
$cams["webcam_1"]["trigger_var"] = true; // true => create varaible and set active when motion
$cams["webcam_1"]["history"] = 50; // Amount of images for history
$cams["webcam_1"]["email"] = 20779 /*[Objekte\E-Mail senden (SMTP)]*/; // instance of SMTP Module, send email notification with image to mail
$cams["webcam_2"]["title"] = "WebCam Haustüre";
$cams["webcam_2"]["url"] = "http://192.168.178.71/image/jpeg.cgi";
$cams["webcam_2"]["user"] = "cam";
$cams["webcam_2"]["pwd"] = "cam";
$cams["webcam_2"]["textposY"] = 450;
$cams["webcam_2"]["trigger_var"] = true;
$cams["webcam_2"]["history"] = 50; // Amount of images for history
$cams["webcam_2"]["email"] = 20779 /*[Objekte\E-Mail senden (SMTP)]*/ ; // instance of SMTP Sender, send email notification with image to mail
$cams["webcam_3"]["title"] = "WebCam 3";
$cams["webcam_3"]["url"] = "http://192.168.178.72/image/jpeg.cgi";
$cams["webcam_3"]["user"] = "admin";
$cams["webcam_3"]["pwd"] = "";
$cams["webcam_3"]["textposY"] = 450;
$cams["webcam_3"]["trigger_var"] = true;
$cams["webcam_3"]["history"] = 20; // Amount of images for history
$cams["webcam_3"]["email"] = 20779 /*[Objekte\E-Mail senden (SMTP)]*/ ; // instance of SMTP Sender, send email notification with image to mail
$c_font = 4;
$c_minpause = 30; // in Sekunden
$c_motionTimeout = 30; // in Sekunden wie lange die BewegungsVariable gesetzt bleibt
$c_historysize = 50; // Percentage of imagesize for history
$c_historypath = IPS_GetKernelDir()."webfront\\user\\webcams\\"; // Gegebenenfalls manuell anlegen
$c_mail_subject = "IPS Webcam Nachricht"; // Subject of mail which will be sent.
/* --------------------------------------------------------------------------------*/
require_once ("settings.ips.php");
$set = new settings;
// Variablen zurücksetzen nach Timeout --------------------------------------
if($_IPS['SENDER'] == 'TimerEvent'){
foreach($cams as $key => $config){
$id = IPS_GetVariableIDByName("Bewegung ".$config["title"], $_IPS['SELF']);
if($id){
SetValue($id,false);
IPS_SetScriptTimer($_IPS['SELF'], 0);
}
}
return;
}
// Notificationcounter zurücksetzen bei Änderung von Typ ----------------------
if($_IPS["SENDER"] == "WebFront"){
SetValue($_IPS["VARIABLE"], $_IPS["VALUE"]);
return;
}
// ----- Mehrfachausführung verhindern. -------------------------------------------
$semName = "SCRIPT_".$_IPS['SELF'];
if (!IPS_SemaphoreEnter($semName, 1000)){
echo "Gleiches Script läuft noch, abbruch!";
return;
// IPS_SemaphoreLeave($semName); // Am Ende des Scriptes anfügen
}
/* *****************************************************************************/
if(!empty($_IPS['CAMID'])){
getImage($_IPS['CAMID']);
// Kamera wurde getriggert durch Bewegung
$trigger_id = CreateVariableByName($_IPS['SELF'],"Bewegung ".$cams[$_IPS['CAMID']]["title"],0);
if($cams[$_IPS['CAMID']]["trigger_var"]){
SetValue($trigger_id,true);
IPS_SetScriptTimer($_IPS['SELF'], $c_motionTimeout);
}
} else {
// jede einzelne versenden
foreach($cams as $key => $cam){
getImage($key);
}
}
IPS_SemaphoreLeave($semName); // Am Ende des Scriptes anfügen
function getImage($cam){
global $cams, $c_font, $c_minpause, $c_historysize, $c_historypath, $c_mail_subject, $set;
$last = $set->getValue($cam);
if(($last + $c_minpause) > time()){
return;
}
// Prüfen ob online
$IPS_Image = IPS_GetKernelDir()."media\\".$cams[$cam]["title"].".jpg";
if(!empty($cams[$cam]["user"])){
$url = str_replace('http://', '', $cams[$cam]["url"]);
$url_login = "http://".$cams[$cam]["user"].":".$cams[$cam]["pwd"]."@$url";
} else {
$url_login = $cams[$cam]["url"];
}
// Prüfen ob online.
$urlInfo = parse_url($url_login);
if(!Sys_Ping($urlInfo["host"],1000))return;
echo "Get Image from $cam.
";
$im = ImageCreateFromJPEG($url_login);
if(!$im){
return;
}
// Save to Media Folder and place some text
$x = 10 ;
$y = $cams[$cam]["textposY"];
$backgroundColor = imagecolorallocate ($im, 255, 255, 255); //white background
$textColor = imagecolorallocate ($im, 255, 255, 255); //black text
$textColor2 = imagecolorallocate ($im, 0, 0, 0); //black text
$string = $cams[$cam]["title"].", ".date("d.m.Y, H:i:s")." Uhr";
imagestring($im, $c_font, $x+1, $y+1, $string, $textColor2);
imagestring($im, $c_font, $x, $y, $string, $textColor);
imagejpeg($im, $IPS_Image);
$set->setValue($cam, time());
// Prüfen ob Mailtrigger aktiv und ob Variable zum Versand gesetzt ist
if($cams[$cam]["email"] != 0){
$mail_notiftype = GetValue(GetWebCamNotificationVar($cam));
if( ($mail_notiftype == 1 ) ||
($mail_notiftype == 2)){
$mail_inst = $cams[$cam]["email"];
$mail_text = "Bewegung an Webcam ".$cams[$cam]["title"]." erkannt.
";
$mail_text .= date("d.m.Y, H:i:s")." Uhr
";
$mail_text .= "Das aktuell aufgenommene Bild befindet sich im Anhang.";
SMTP_SendMailAttachment($mail_inst,$c_mail_subject." (".$cams[$cam]["title"].")",$mail_text,$IPS_Image);
if($mail_notiftype == 1){
SetValue(GetWebCamNotificationVar($cam),0);
}
}
}
// Webcam History aktiv?
if($cams[$cam]["history"] != 0){
if(!is_dir($c_historypath))mkdir($c_historypath);
$dir_target = $c_historypath.$cam;
if(!is_dir($dir_target))mkdir($dir_target);
$fn_target = $dir_target ."\\".date("Y-m-d_H.i.s").".jpg";
// Keep History files for WebCam
$image = new SimpleImage();
$image->load($IPS_Image);
$image->scale($c_historysize);
$image->save($fn_target);
// Alte Files aufräumen
foreach (glob($dir_target."\\*.jpg") as $fn) {
$files[] = $fn;
}
sort($files);
if(count($files) > $cams[$cam]["history"]){
for($x = 0; $x < (count($files)-$cams[$cam]["history"]); $x++){
//echo($files[$x]."
");
unlink($files[$x]);
}
}
// History Variable setzen
$HTML_NAME = "Webcam History";
$HTMLID = @IPS_GetVariableIDByName($HTML_NAME, $_IPS['SELF']);
if(!$HTMLID){
$HTMLID = CreateVariableByName($_IPS['SELF'],$HTML_NAME,3,"~HTMLBox");
}
SetValue($HTMLID,'<iframe src="user/webcams/" width="100%" frameBorder="0" height="600"></iframe>');
} // Cam History
}
function GetWebCamNotificationVar($cam){
global $cams;
$varProfile = "Info_Message";
if(!@IPS_GetVariableProfile($varProfile)){
IPS_CreateVariableProfile($varProfile,1);
IPS_SetVariableProfileAssociation($varProfile, 0, "Keine", "", -1);
IPS_SetVariableProfileAssociation($varProfile, 1, "Einmalig", "", -1);
IPS_SetVariableProfileAssociation($varProfile, 2, "Dauerhaft", "", -1);
}
$varCategory = IPS_GetCategoryIDByName("Webcam Notification",$_IPS["SELF"]);
if(!$varCategory){
$varCategory = IPS_CreateCategory();
IPS_SetParent($varCategory,$_IPS["SELF"]);
IPS_SetName($varCategory, "Webcam Notification");
}
$camVars = IPS_GetChildrenIDs($varCategory);
$varDesc = "Notification for |$cam|
!DIESEN TEXT NICHT ÄNDERN!";
$notID = 0;
foreach($camVars as $varID){
$varInfo = IPS_GetObject($varID);
if($varInfo["ObjectInfo"] == $varDesc){
$notID = $varID;
};
}
if ($notID == 0){
$notID = CreateVariableByName($varCategory,$cams[$cam]["title"],1,$varProfile);
IPS_SetInfo($notID,$varDesc);
SetValue($notID,2); // Dauerhaft anschalten
//Webfront Trigger setzen
IPS_SetVariableCustomAction($notID,$_IPS["SELF"]);
}
return $notID;
}
/* HELPER FUNCTIONS -------------------------------------------------------------*/
/* CreateVariableByName -------------------------------------------------------------------------
id = Wo soll sie hängen
name = Name der Variablen
type: 0: boolean
1: integer
2: float
3: string
profil: Variablenprofi
*/
function CreateVariableByName($id, $name, $type, $profile = "")
{
# type: 0=boolean, 1 = integer, 2 = float, 3 = string;
global $IPS_SELF;
$vid = @IPS_GetVariableIDByName($name, $id);
if($vid === false)
{
$vid = IPS_CreateVariable($type);
IPS_SetParent($vid, $id);
IPS_SetName($vid, $name);
IPS_SetInfo($vid, "this variable was created by script #$IPS_SELF");
if($profile !== "") { IPS_SetVariableCustomProfile($vid, $profile); }
}
return $vid;
}
/*
* File: SimpleImage.php
* Author: Simon Jarvis
* Copyright: 2006 Simon Jarvis
* Date: 08/11/06
* Link: http://www.white-hat-web-design.co.uk/articles/php-image-resizing.php
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details:
* http://www.gnu.org/licenses/gpl.html
*
*/
class SimpleImage {
var $image;
var $image_type;
function load($filename) {
$image_info = getimagesize($filename);
$this->image_type = $image_info[2];
if( $this->image_type == IMAGETYPE_JPEG ) {
$this->image = imagecreatefromjpeg($filename);
} elseif( $this->image_type == IMAGETYPE_GIF ) {
$this->image = imagecreatefromgif($filename);
} elseif( $this->image_type == IMAGETYPE_PNG ) {
$this->image = imagecreatefrompng($filename);
}
}
function save($filename, $image_type=IMAGETYPE_JPEG, $compression=75, $permissions=null) {
if( $image_type == IMAGETYPE_JPEG ) {
imagejpeg($this->image,$filename,$compression);
} elseif( $image_type == IMAGETYPE_GIF ) {
imagegif($this->image,$filename);
} elseif( $image_type == IMAGETYPE_PNG ) {
imagepng($this->image,$filename);
}
if( $permissions != null) {
chmod($filename,$permissions);
}
}
function output($image_type=IMAGETYPE_JPEG) {
if( $image_type == IMAGETYPE_JPEG ) {
imagejpeg($this->image);
} elseif( $image_type == IMAGETYPE_GIF ) {
imagegif($this->image);
} elseif( $image_type == IMAGETYPE_PNG ) {
imagepng($this->image);
}
}
function getWidth() {
return imagesx($this->image);
}
function getHeight() {
return imagesy($this->image);
}
function resizeToHeight($height) {
$ratio = $height / $this->getHeight();
$width = $this->getWidth() * $ratio;
$this->resize($width,$height);
}
function resizeToWidth($width) {
$ratio = $width / $this->getWidth();
$height = $this->getheight() * $ratio;
$this->resize($width,$height);
}
function scale($scale) {
$width = $this->getWidth() * $scale/100;
$height = $this->getheight() * $scale/100;
$this->resize($width,$height);
}
function resize($width,$height) {
$new_image = imagecreatetruecolor($width, $height);
imagecopyresampled($new_image, $this->image, 0, 0, 0, 0, $width, $height, $this->getWidth(), $this->getHeight());
$this->image = $new_image;
}
}
?>
Oben im Script wird folgender Pfad verwendet um die History der Webcam Motion zu speichern
$c_historypath = IPS_GetKernelDir().„webfront\user\webcams\“; // Gegebenenfalls manuell anlegen
in diesen Pfad eine Datei mit folgendem Inhalt anlegen (index.php)
Dieses SCript listet alle Historien-Bilder der Webcam auf und das obige Script erstellt eine Variable für’s webfront mit einem Iframe wo diese Bilder dann dargestellt werden.
Ich habe die Software „Blue Iris“ am Laufen und sende über das externe Programm IPSCommand bei Bewegungserkennung eine Änderung. Die Bewegungserkennung über die Software ist z.T. deutlich besser als die integrierte Erkennung in den Kameras, vor allem bei billigen (z.B. Foscam) Kameras.
ich baue mir gerade die Raspberry surveillance camera, funktioniert bis jetzt auch schon ganz gut. Als Gehäuse habe ich mal wieder den guten alten 500W Hallogenstrahler umgebaut. Die Motion Software wird auch immer wieder verbessert und erweitert und der Raspberry ist natürlich für alle Programmierungen offen.