ACHTUNG: Mittlerweile ist die Funktionalität direkt im IPSStudio integriert.

ACHTUNG: Alternativ ist dieses Skript auch als Modul verfügbar – siehe Modul – Synchronisieren von Views

Ich möchte hier mal ein Skript vorstellen, mit dem man eine View kopieren kann und dabei gleichzeitig die Auflösung ändern kann.

So ist es zum Beispiel möglich die View eines iPad auf eine Android View mit höherer Auflösung zu kopieren.

Für die X und Y Achse kann ein beliebiger Faktor angegeben werden, Ziel View wird mit der Source View überschrieben (vorher unbedingt Backup machen).

In manchen Fällen muss man die generierte View noch etwas nacharbeiten.

<? 
    /**
     * @file          IPSView_ResizeView.php
     * @author        brownson
     * @version
     *   Version 1.0, 2015-08-10 brownson: Initiale Version<br/>
     *   Version 1.1, 2016-01-27 brownson: Reduced Memory Usage<br/>
     *
     * IPSView Skript um eine View auf eine andere View zu kopieren inklusive
     * Umrechung der Skalierung von X und Y Achse.
     *
     * Konfiguration Einstellungen:
     *   * $masterViewID     - ID der View von der kopiert werden soll
     *   * $childViewID      - ID der View auf die kopiert werden soll
     *   * $childViewFactorX - Umrechnungsfaktor für die X Achse
     *   * $childViewFactorY - Umrechnungsfaktor für die Y Achse
     *
     */

    // Konfiguration
    $masterViewID        = 12345;
    $childViewID         = 67890;
    $childViewFactorX    = 2.5;
    $childViewFactorY    = 2.13;

    // -------------------------------------------------------------------------

    // Konfiguration überprüfen
    if ($masterViewID == '') {
        die('Bitte geben Sie eine MasterViewID in der Konfiguration an.');
    }

    // Konfiguration überprüfen
    if ($childViewID == '') {
        die('Bitte geben Sie eine ChildViewID in der Konfiguration an.');
    }

    echo "Convert View with FactorX=$childViewFactorX and FactorY=$childViewFactorY".PHP_EOL;
    echo "Available Memory: ".ini_get('memory_limit').' ';
echo "".PHP_EOL;

   showMemoryUsage('Startup: ');

    $viewProperties = getViewProperties ($childViewID);
    $masterObj      = getViewObject($masterViewID);

    // Build Result Object
    $resultObj                   = resizeView ($masterObj, $childViewFactorX, $childViewFactorY);
    $resultObj['ViewRatio12']    = $viewProperties['ViewRatio12'];
    $resultObj['Name']           = $viewProperties['Name'];
    $resultObj['ID']             = $childViewID;
    $resultObj['Width']          = $viewProperties['Width'];
    $resultObj['Height']         = $viewProperties['Height'];
    $resultObj['Client']         = $viewProperties['Client'];
    $resultObj['Hardware']       = $viewProperties['Hardware'];

   showMemoryUsage('Build Result:');
   $masterObj = null;
   
    // Write Data to View
    writeViewContent ($childViewID, $resultObj);
    $resultObj = null;
   showMemoryUsage('finished:');

    echo ' '.PHP_EOL;
    echo '============================================================='.PHP_EOL;
    echo 'Successfully finished synchronization                        '.PHP_EOL;
    echo '============================================================='.PHP_EOL;

    // ----------------------------------------------------------------------------------------------------
    function writeViewContent ($ID, $viewObj) {
       $name    = IPS_GetName($ID);
        // Write Data to View

        $data        = json_encode($viewObj);
       showMemoryUsage("json_encode '$name'");
        $viewObj = null;

        $content     = base64_encode($data);
       showMemoryUsage("base64_encode '$name'");
        $data = null;

        IPS_SetMediaContent($ID, $content);
       showMemoryUsage("IPS_SetMediaContent '$name'");
        $resultContent = null;
    }

    // ----------------------------------------------------------------------------------------------------
    function getViewProperties ($ID) {
       $viewObj = getViewObject($ID);
       $name    = IPS_GetName($ID);

        $result                   = array();
        $result['ViewRatio12']    = $viewObj['ViewRatio12'];
        $result['Name']           = $viewObj['Name'];
        $result['ID']             = $viewObj['ID'];
        $result['Width']          = $viewObj['Width'];
        $result['Height']         = $viewObj['Height'];
        $result['Client']         = $viewObj['Client'];
        $result['Hardware']       = $viewObj['Hardware'];
       showMemoryUsage("getViewProperties '$name'");

       return $result;
    }

    // ----------------------------------------------------------------------------------------------------
    function getViewObject($ID) {
       $name = IPS_GetName($ID);
    
        // Read Content of View
        $content     = IPS_GetMediaContent($ID);
       showMemoryUsage("IPS_GetMediaContent '$name'");
        if ($content===false) {
            die("Media Objekt von Master konnte NICHT gefunden werden");
        }

        $data         = base64_decode($content);
       showMemoryUsage("base64_decode '$name'");
        $content      = null;

        $obj          = json_decode($data, true);
       showMemoryUsage("json_decode '$name'");
        $data         = null;
         if ($obj===false) {
            die("JSON Objekt von View '$name' konnte NICHT dekodiert werden");
        }
        return $obj;
    }

    // ----------------------------------------------------------------------------------------------------
    function resizeView ($jsonObj, $factorX, $factorY) {
        $factor = $factorX > $factorY ? $factorY : $factorX;
        $pages  = array();
        foreach ($jsonObj['Pages'] as $page) {
           //echo "Process Page=".$page['DisplayName'].PHP_EOL;
            $controls = array();
            foreach ($page['Controls'] as $control) {
                $control['Width']     = round($control['Width'] * $factorX);
                $control['Height']    = round($control['Height'] * $factorY);
                $control['LocationX'] = round($control['LocationX'] * $factorX);
                $control['LocationY'] = round($control['LocationY'] * $factorY);
                if (array_key_exists('Font', $control) && array_key_exists('Size', $control['Font'])) {
                   $control['Font']['Size'] = round($control['Font']['Size'] * $factor);
                }
                if (array_key_exists('CR1', $control)) $control['CR1'] = round($control['CR1'] * $factor);
                if (array_key_exists('CR2', $control)) $control['CR2'] = round($control['CR2'] * $factor);
                if (array_key_exists('CR3', $control)) $control['CR3'] = round($control['CR3'] * $factor);
                if (array_key_exists('CR4', $control)) $control['CR4'] = round($control['CR4'] * $factor);
                $controls[] = $control;
            }
            $page['Controls']    = $controls;
            $page['PopupWidth']  = round($page['PopupWidth'] * $factorX);
            $page['PopupHeight'] = round($page['PopupHeight'] * $factorY);
            $pages[] = $page;
        }
        $jsonObj['Pages'] = $pages;

        return $jsonObj;
    }

    // ----------------------------------------------------------------------------------------------------
    function showMemoryUsage($statusMessage) {
        $statusMessage = substr($statusMessage.'                                                            ', 0, 60);
        $memory = round(memory_get_usage() / 1024 / 1024, 2);
       echo $statusMessage . ' UsedMemory='.$memory. " MB".PHP_EOL;
    }

?>

Wer diesen Vorgang auch noch komplett automatisieren möchte, kann das mit folgendem Skript realisieren:

Beim Aufruf des Skriptes wird der komplette Inhalt der Masterview auf die spezifizierte Targetview kopiert und dabei alle Seiten und Steuerelemente entsprechend den eingestellten Faktoren in X und Y Richtung neu skaliert.

<?
	/**
	 * @file          IPSView_SyncAndroidTestview.php
	 * @author        brownson
	 * @version
	 *   Version 1.0, 2015-06-09 brownson: Initiale Version<br/>
	 *
	 * IPSView Skript um eine 2 Views zu synchronisieren
	 *
	 * Konfiguration Einstellungen:
	 *   * $masterViewID    - ID der Master View
	 *   * $androidViewID   - ID der View die synchronisiert werden soll
	 *   * $resizeScriptID  - ID des Scriptes das zum Resize aufgerufen
	 *                        werden soll
	 *
	 */

	// Konfiguration
	$masterViewID     = 12586 /*[TestView_v2.2.ipsView]*/;
	$androidViewID    = 23327 /*[TestView_v2.2A.ipsView]*/;
	$resizeScriptID   = 15584 /*[TestView_v2.2A.ipsView]*/;

	// -------------------------------------------------------------------------

	// Konfiguration überprüfen
	if ($masterViewID == '') {
		echo 'Bitte geben Sie eine ViewID in der Konfiguration an.'.PHP_EOL;
		return;
	}

	$masterMedia       = IPS_GetMedia($masterViewID);
	$masterTimestamp   = array_key_exists('MediaUpdated', $masterMedia)
	                        ? $masterMedia['MediaUpdated'] /*v4.x*/
				: $masterMedia['LastUpdate'] /*v3.x*/;
	$androidMedia      = IPS_GetMedia($androidViewID);
	$androidTimestamp  = array_key_exists('MediaUpdated', $androidMedia)
	                        ? $androidMedia['MediaUpdated'] /*v4.x*/
				: $androidMedia['LastUpdate'] /*v3.x*/;

	if ($masterTimestamp >  $androidTimestamp /*Masterview has changed*/) {
		echo "MasterView has changed ...".PHP_EOL;

		IPS_RunScriptWait($resizeScriptID);
	}
?>

 

Das Script überprüft die Timestamp der beiden Views und ruft bei einer Änderung der Masterview das Resize Skript auf. Den nötigen Timer für einen zyklischen Aufruf des Skriptes  (zb alle 10 Sekunden) muss noch manuell dazu angelegt werden.

[Update 2016-06-20]

Modifizierung des Skriptes um den Speicherverbrauch in PHP zu optimieren.