Ansteuerung Foscam via CGI

Hi zusammen,

habe gerade mit meiner neuen Foscam-Kamera (FI9828P_V2) rumgespielt und die Ansteuerung via CGI Aufruf ausprobiert.
Dabei ist ein kleines Script bei rausgekommen, was man vielleicht an seine eigenen Wünsche anpassen kann.

Was kann es:

[ul]
[li]die Bildeinstellungen lesen und schreiben[/li][li]die Kamera bewegen mittels Pfeiltasten (Achtung, gestoppt wird dem Kreuz mit Kreis drumherum ;-)[/li][li]einen vordefinierten Punkt anfahren (orangner Button)[/li][li]ZoomIn & ZoomOut (rechten 3 grauen Buttons)[/li][/ul]

Was kann es nicht:

[ul]
[li]durch die Verzögerung die richtige Stelle anfahren ist fast unmöglich[/li][li]für Scharf stellen (FadeIn & FadeOut) habe ich keinen Aufruf gefunden[/li][li]3 Buttuns (x) sind noch frei ;-)[/li][/ul]

Im Webfront sieht:

Das Script:


<?php
################################################################################
# Scriptbezeichnung: Foscam.Control.ips.php
# Version: 1.0.20190326
# Author:  Heiko Wilknitz (@Pitti)
#
# Steuerung einer FOSCAM IP Kamera via CGI Schnittstelle
# Erfolgreich getestet mit FI9828P_V2
#
# ------------------------------ Installation ----------------------------------
#
# Dieses Skript richtet automatisch alle nötigen Objekte bei manueller
# Ausführung ein. Eine weitere manuelle Ausführung setzt alle benötigten Objekte
# wieder auf den Ausgangszustand.
#
# - Neues Skript erstellen
# - Diesen PHP-Code hineinkopieren
# - Abschnitt 'Konfiguration' den eigenen Gegebenheiten anpassen 
# - Skript Abspeichern
# - Skript Ausführen
# - Visualisierung per Link auf entstandene Variablen erstellen
#
# ------------------------------ Visualisierung --------------------------------
#
# Kann natürlich jeder machen wie er möchte, hier ein schematischer Vorschlag
# wie man vorgehen könnte:
#
# Zweischpaltiges Splitpane Layout (Vertikal 50:50)
#
# ------------------------------ Changelog -------------------------------------
#
# 26.03.2019 - Initalversion (v1.0)
#
# ------------------------------ Konfiguration ---------------------------------
#
# WebFront-ID für Fehlerausgabe
$wfc = 52523;
#
# Kamera IP
$ip = '192.168.x.x';
# Port 
$port = 88;
# User
$usr = 'admin';
# Kennwort
$pw = 'admin';
# CGI URL Part
$cgi = '/cgi-bin/CGIProxy.fcgi?cmd=<COMMAND>';
# Preset Point
$pnt = 'hierhin';
#
################################################################################

// INSTALLATION
if ($_IPS['SENDER']=='Execute') {
	$pos = 0;
	// Variablen
	$vid = CreateVariableByName($_IPS['SELF'], "Aktualisierung", 1, 'IPS.Update', $pos++);
	IPS_SetVariableCustomAction($vid, $_IPS['SELF']);
	$vid = CreateVariableByName($_IPS['SELF'], 'Helligkeit', 1, '~Intensity.100', $pos++);
	IPS_SetVariableCustomAction($vid, $_IPS['SELF']);
	$vid = CreateVariableByName($_IPS['SELF'], 'Kontrast', 1, '~Intensity.100', $pos++);
	IPS_SetVariableCustomAction($vid, $_IPS['SELF']);
	$vid = CreateVariableByName($_IPS['SELF'], 'Farbton', 1, '~Intensity.100', $pos++);
	IPS_SetVariableCustomAction($vid, $_IPS['SELF']);
	$vid = CreateVariableByName($_IPS['SELF'], 'Sättigung', 1, '~Intensity.100', $pos++);
	IPS_SetVariableCustomAction($vid, $_IPS['SELF']);
	$vid = CreateVariableByName($_IPS['SELF'], 'Schärfe', 1, '~Intensity.100', $pos++);
	IPS_SetVariableCustomAction($vid, $_IPS['SELF']);
	$vid = CreateVariableByName($_IPS['SELF'], 'Steuerung', 3, '~HTMLBox', $pos++);
    BuildHtml($vid);
}
// WEBFRONT
else if($_IPS['SENDER'] == 'WebFront') {
    // Wer war der Auslöser?
	$name = IPS_GetName($_IPS['VARIABLE']);
	// Infos holen und setzen
	if( $name == 'Aktualisierung') {
		GetImageSettings();		
		// Aktualisierung Button zurückstellen
		$_IPS['VALUE'] = 0;
	// Einstellungen setzen
	} elseif( $name == 'Helligkeit') {
		SetImageSetting('setBrightness&brightness='.$_IPS['VALUE']);		
	} elseif( $name == 'Kontrast') {
		SetImageSetting('setContrast&constrast='.$_IPS['VALUE']);		
	} elseif( $name == 'Farbton') {
		SetImageSetting('setHue&hue='.$_IPS['VALUE']);		
	} elseif( $name == 'Sättigung') {
		SetImageSetting('setSaturation&saturation='.$_IPS['VALUE']);		
	} elseif( $name == 'Schärfe') {
		SetImageSetting('setSharpness&sharpness='.$_IPS['VALUE']);		
	}
   // Speichern
	SetValue($_IPS['VARIABLE'], $_IPS['VALUE']);
}

# ----------------------------- Functions ---------------------------------

// Alle Bildeigenschaften abholen
function GetImageSettings()
{
global $wfc;
    // Daten holen    
    $data = ReceiveData('getImageSetting');
    if ($data === false) {
	    WFC_SendNotification($wfc, 'Foscam', 'Fehler bei Image Settings!', 'Information', 5);
    }
	$vid = CreateVariableByName($_IPS['SELF'], 'Helligkeit', 1);
    SetValueInteger($vid, intval($data->brightness));
	$vid = CreateVariableByName($_IPS['SELF'], 'Kontrast', 1);
    SetValueInteger($vid, intval($data->contrast));
	$vid = CreateVariableByName($_IPS['SELF'], 'Farbton', 1);
    SetValueInteger($vid, intval($data->hue));
	$vid = CreateVariableByName($_IPS['SELF'], 'Sättigung', 1);
    SetValueInteger($vid, intval($data->saturation));
	$vid = CreateVariableByName($_IPS['SELF'], 'Schärfe', 1);
    SetValueInteger($vid, intval($data->sharpness));
}		

// Bildeigenschaften setzen 
function SetImageSetting($cmd)
{
global $wfc;
    // Daten holen    
    $data = ReceiveData($cmd);
    if ($data === false) {
	    WFC_SendNotification($wfc, 'Foscam', 'Fehler bei Ändern der Bildeinstellungen!', 'Information', 5);
    }
}		

// CGI Aufruf Wrapper
function ReceiveData($command)
{
global $ip, $port, $usr, $pw, $cgi;

    // build url
    $cmd = str_replace('<COMMAND>', $command, $cgi);
    $url = 'http://'.$ip.':'.$port.$cmd.'&usr='.$usr.'&pwd='.$pw;
  	$ret = file_get_contents($url);
    $xml = new SimpleXMLElement($ret);
    if ($xml->result == 0) {
        return $xml;
    }
    return false;
}

// Der einfachheit halber per Heredoc Syntax 
function BuildHtml($id) 
{
global $ip, $port, $usr, $pw, $cgi, $pnt;

// Vorbereitung für JS
$cmd = str_replace('<COMMAND>', '', $cgi);
$prefix = 'http://'.$ip.':'.$port.$cmd;
$suffix = '&usr='.$usr.'&pwd='.$pw;    
$point  = 'ptzGotoPresetPoint&name='.$pnt;

// HTML in einem Rutsch
$html = <<< EOT
<style>
.btn {display:inline-block;height:37px;width:40px;text-align: center;border:1px solid rgba(255, 255, 255, 0.1);margin:1px; font-size:32px;line-height:35px;}
.dir {padding: 5px; color: rgb(255, 255, 255); background-color: #0d1724; background-image: linear-gradient(top,rgba(255,255,255,0.18) 0,rgba(0,0,0,0.3) 50%,rgba(0,0,0,0.3) 100%); background-image: -o-linear-gradient(top,rgba(255,255,255,0.18) 0,rgba(0,0,0,0.3) 50%,rgba(0,0,0,0.3) 100%); background-image: -moz-linear-gradient(top,rgba(255,255,255,0.18) 0,rgba(0,0,0,0.3) 50%,rgba(0,0,0,0.3) 100%); background-image: -webkit-linear-gradient(top,rgba(255,255,255,0.18) 0,rgba(0,0,0,0.3) 50%,rgba(0,0,0,0.3) 100%); background-image: -ms-linear-gradient(top,rgba(255,255,255,0.18) 0,rgba(0,0,0,0.3) 50%,rgba(0,0,0,0.3) 100%); }
.pos {padding: 5px; color: rgb(255, 255, 255); background-color: orange; background-image: linear-gradient(top,rgba(255,255,255,0.18) 0,rgba(0,0,0,0.3) 50%,rgba(0,0,0,0.3) 100%); background-image: -o-linear-gradient(top,rgba(255,255,255,0.18) 0,rgba(0,0,0,0.3) 50%,rgba(0,0,0,0.3) 100%); background-image: -moz-linear-gradient(top,rgba(255,255,255,0.18) 0,rgba(0,0,0,0.3) 50%,rgba(0,0,0,0.3) 100%); background-image: -webkit-linear-gradient(top,rgba(255,255,255,0.18) 0,rgba(0,0,0,0.3) 50%,rgba(0,0,0,0.3) 100%); background-image: -ms-linear-gradient(top,rgba(255,255,255,0.18) 0,rgba(0,0,0,0.3) 50%,rgba(0,0,0,0.3) 100%); }
.ops {padding: 5px; color: rgb(255, 255, 255); background-color: grey; background-image: linear-gradient(top,rgba(255,255,255,0.18) 0,rgba(0,0,0,0.3) 50%,rgba(0,0,0,0.3) 100%); background-image: -o-linear-gradient(top,rgba(255,255,255,0.18) 0,rgba(0,0,0,0.3) 50%,rgba(0,0,0,0.3) 100%); background-image: -moz-linear-gradient(top,rgba(255,255,255,0.18) 0,rgba(0,0,0,0.3) 50%,rgba(0,0,0,0.3) 100%); background-image: -webkit-linear-gradient(top,rgba(255,255,255,0.18) 0,rgba(0,0,0,0.3) 50%,rgba(0,0,0,0.3) 100%); background-image: -ms-linear-gradient(top,rgba(255,255,255,0.18) 0,rgba(0,0,0,0.3) 50%,rgba(0,0,0,0.3) 100%); }
</style>
<script>
function focus(pos) {
}
function zoom(pos) {
  var zoom = "";
  switch(pos) {
    case 0: zoom = zoom + 'zoomStop'; break;
    case 1: zoom = zoom + 'zoomIn'; break;
    case 2: zoom = zoom + 'zoomOut'; break;
    default:// code block
  }
  var url = "$prefix" + zoom + "$suffix";
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      // Cursor setzen
    }
  };
  xhttp.open("GET", url, true);
  xhttp.send();
  //alert(url);
}
function move(pos) {
  var ptz = "";
  switch(pos) {
    case 0: ptz = "$point"; break;
    case 1: ptz = 'ptzMoveTopLeft';break;
    case 2: ptz = 'ptzMoveUp'; break;
    case 3: ptz = 'ptzMoveTopRight'; break;
    case 4: ptz = 'ptzMoveLeft'; break;
    case 5: ptz = 'ptzStopRun'; break;
    case 6: ptz = 'ptzMoveRight'; break;
    case 7: ptz = 'ptzMoveBottomLeft'; break;
    case 8: ptz = 'ptzMoveDown'; break;
    case 9: ptz = 'ptzMoveBottomRight'; break;
    default:// code block
  }
  var url = "$prefix" + ptz + "$suffix";
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      // Cursor setzen
    }
  };
  xhttp.open("GET", url, true);
  xhttp.send();
  //alert(url);
}
</script>
<center>
	<table>
		<tr>
			<td><div id="btnMoveTopLeft" class="dir btn" onclick="move(1)"> ⬉</div></td>
			<td><div id="btnMoveUp" class="dir btn" onclick="move(2)">⬆</div></td>
			<td><div id="btnMoveTopRight" class="dir btn" onclick="move(3)">⬈</div></td>
			<td><div id="btnZoomIn" class="ops btn" onclick="zoom(1)">+</div></td>
		</tr>
		<tr>
			<td><div id="btnMoveLeft"  class="dir btn" onclick="move(4)">⬅</div></td>
			<td><div id="btnMoveStop" class="ops btn" onclick="move(5)">⮿</div></td>
			<td><div id="btnMoveRight"   class="dir btn" onclick="move(6)">➡</div></td>
			<td><div id="btnZoomStop" class="ops btn" onclick="zoom(0)">⮿</div></td>
		</tr>
		<tr>
			<td><div id="btnBottomLeft"  class="dir btn" onclick="move(7)">⬋</div></td>
			<td><div id="btnMoveDown"  class="dir btn" onclick="move(8)">⬇</div></td>
			<td><div id="btnBottomRight" class="dir btn" onclick="move(9)">⬊</div></td>
			<td><div id="btnZoomOut" class="ops btn" onclick="zoom(2)">−</div></td>
		</tr>
		<tr>
			<td><div id="btnFocusIn"  class="ops btn" onclick="focus(1)">x</div></td>
			<td><div id="btnFocusStop"  class="ops btn" onclick="focus(0)">x</div></td>
			<td><div id="btnFocusOut" class="ops btn" onclick="focus(2)">x</div></td>
			<td><div id="btnMoveReturn" class="pos btn" onclick="move(0)">⨀</div></td>
		</tr>
	</table>
</center>
EOT;
	SetValueString($id, $html);
}

// Erzeugt eine Variable unterhalb {id} mit dem Namen {name} vom Typ [type}
// Existiert die Variable schon wird diese zurückgeliefert.
// Type: 0 = Boolean, 1 = Integer, 2 = Float, 3 = String
// Profile: leer für kein Profil, sonst Profilnamen
function CreateVariableByName($id, $name, $type, $profile = '', $pos = null) 
{
	$vid = @IPS_GetVariableIDByName($name, $id); 
	if($vid===false) {
		$vid = IPS_CreateVariable($type); 
		IPS_SetParent($vid, $id); 
		IPS_SetName($vid, $name); 
		if($profile !== '') { 
			IPS_SetVariableCustomProfile($vid, $profile); 
		}
		if($pos !== null) { 
			IPS_SetPosition($vid, $pos); 
		}
	}
	return $vid; 
}

?>

Viel Spaß
Heiko

Hallo Heiko,

Beeindruckend finde ich insbesondere die Steuerung unten links.
Magst Du erzählen wie Du die erstellt hast?
Hast Du einen Editor oder ähnliches?

Joachim

Danke Joachim!

Nein, kein Editor. Ich habe mal vor langer Zeit die Buttons entwickelt (abgeleitet vom IPS Button Design) für die Darstellung der „Meldungsanzeige im WebFront“. Dannach hatte ich mal ein Gaudi-Script „Taschenrechner“ geschrieben, wo ich mit den Buttons rumexperimentiert hatte. Das war jetzt mal eine ganz schnelle Wiederverwendung aus diesem Script - auch hier alles im Forum zu finden.

Ich liebe Copy&Paste :wink: … und dabei immer noch ein Stück optimieren :smiley:

Gruß Heiko