Umgebung:
Wirksystem unter Windows mit IPS 3.4, auf dem Skripte erstellt werden.
Ein oder mehrere Raspis mit IPS 4.0, auf denen die verwendeten Skripte auf dem neuesten Stand gehalten werden sollen.
Skript:
Das nachfolgende Skript verwendet JSON, deshalb müssen Lizenz-Benutzernamen und das Fernzugriff Kennwort für jedes System zur Verfügung gestellt werden.
Es bietet sich an, diese Informationen in ein eigenes Skript zu schreiben, damit es beliebig in andere Skripte inkludiert werden kann, der Name (hier „ObjIDsLAN.inc.php“ ist bindend, da damit aufgerufen wird).
Für jedes IPS-System existiert ein Index-Eintrag in dem folgendes individuell eingetragen werden muß
- Name des Systems als Index
- ‚IP‘ => IP-Adresse
- ‚PW‘ => Fernzugriff Kennwort
Der Lizenz-Benutzername muß im Index-Eintrag ‚Svr1‘ unter ‚Li‘ eingetragen werden
<?
/*
* File mit Kennwerten des LAN's für Devices.
*
* @file ObjIDsLAN.inc.php
* @author Harald Hertlein
* @version 21.09.15 00:09
* Remark: OS-unabhängig
*/
$LAN = array (//
'Svr1' => array (
'IP' => '192.168.0.6',
'Port' => '80', // Port unter dem der PC per JSON erreichbar ist
'Li' => 'H?????@??????.de', // Lizenz-Nehmer
'PW' => '?????', // auf dem PC eingestelltes IPS-Paßwort
'IPS' => '3.40;12.08.15;#3775',
),
'RaspiA1' => array (
'IP' => '192.168.0.81',
'Port' => '3777',
'PW' => '?????',
'IPS' => '4.00;07.10.2015;b3ed15e7',
),
'RaspiA2' => array (
'IP' => '192.168.0.82',
'Port' => '3777',
'PW' => '????',
'IPS' => '4.00;06.10.2015;43cd1657489d',
),
);
?>
In das folgende Arbeitsskript muß dann nur noch der File-Name des zu übertragenden Skriptes und der/die PCs eingetragen werden, zu denen das Skript transferiert werden soll.
<?
/*
* @file IPS2Beitrag_SkriptTransfer.ips.php
* @author Harald Hertlein
* @version 21.10.15 17:03
*
* Läuft auf dem zentralen Arbeitssystem und transferiert Skripte auf die Raspis
*
*/
// Definiere erst mal die Parameter (PCs, Skript)
//$PC = 'RaspiA1'; // einer, wenn auskommentiert alle
$Skript = 'IPS2Beitrag_SkriptAgent.ips.php';
$StarteSkript = 1; // wenn gesetzt, wird das Skript auf dem Remote-PC gestartet, sofern es dort benannt wurde
include_once "ObjIDsLAN.inc.php";
if (isset ($PC)) {
$PCs = array ($PC);
} else {
$PCs = array (
'RaspiA1',
'RaspiA2',
);
}
foreach ($PCs as $PC) {
$EAObj1 = @IPS_GetScriptIDByFile ($Skript);
if ($EAObj1 === false) {
echo "
Lokales Skript '$Skript' nicht gefunden!";
return;
} else {
echo "
Lokales Skript '$Skript' hat die Objekt-ID " . $EAObj1;
}
// $rpc = new JSONRPC("http://user:password@'IP':'Port'/api/");
$rpc = new JSONRPC ("http://" . $LAN['Svr1']['Li'] . ':' . $LAN[$PC]['PW'] . '@' . $LAN[$PC]['IP'] . ':' . $LAN[$PC]['Port'] . '/api/');
// $EAObj2 = $rpc -> IPS_GetScriptIDByFile ($Skript); führt bei Nichtexistenz zu einem JSON-Fehler, deshalb
$Liste = $rpc -> IPS_GetScriptList (); // von hinten durch die Brust ins Auge
$EAObj2 = false;
foreach ($Liste as $SkriptID) {
$GetScript = $rpc -> IPS_GetScript ($SkriptID);
if ($GetScript['ScriptFile'] == $Skript) {
$EAObj2 = $GetScript['ScriptID'];
break;
}
}
if ($EAObj2 === false) {
echo "
Remotes Skript '$Skript' nicht gefunden!";
$NameOK = false;
$EAObj2 = $rpc -> IPS_CreateScript (0); // Als ObjektName
//$rpc -> IPS_SetName ($EAObj2, substr ($Skript, 0, stripos ($Skript, '.'))); // entweder gekürzten Datei-Namen
$rpc -> IPS_SetName ($EAObj2, $Skript); // oder vollen Datei-Namen (entsprechend auskommentieren)
echo "
Remotes Skript '$Skript' angelegt mit der Objekt-ID " . $EAObj2 . " auf PC '$PC'";
//$rpc -> rename (IPS_GetKernelDir () . 'scripts/' . $EAObj2 . '.ips.php', IPS_GetKernelDir () . 'scripts/' . $Skript); // diese Funktion crashed weil sie rename nicht findet
//$rpc -> IPS_SetScriptFile ($EAObj2, $Skript); // diese Funktion crashed, wenn $Skript nicht vorhanden, deshalb leider
echo "
ACHTUNG!!: Remotes Skript '" . $EAObj2 . ".ips.php' auf PC '$PC' muß umbenannt werden in '$Skript'";
$NameOK = false;
} else {
echo "
Remotes Skript '$Skript' hat die Objekt-ID " . $EAObj2 . " auf PC $PC";
$NameOK = true;
}
$rpc -> IPS_SetScriptContent ($EAObj2, IPS_GetScriptContent ($EAObj1));
if ($StarteSkript && $NameOK) {
echo " und wird ausgeführt!!";
$Msg = $rpc -> IPS_RunScriptWait ($EAObj2);
print ("
---------- Meldung von PC $PC ---------
$Msg---------------------------------------
");
}
}
?>
Die für IPS zur Verfügung gestellte JSON-RPC API hat den Mangel, dass keine PHP-Befehle per Remote ausgeführt werden können. Wenn das zu transferierende Skript auf dem Ziel-PC noch nicht existiert, kann der File-Name nicht korrekt wiedergegeben werden.
Beim Ersttransfer eines Skriptes muß daher per Konsole auf dem Ziel-PC der File-Name korriegiert werden
Erfolgt dies nicht, wird beim nächsten Update ein neues Skript angelegt.
Existiert der File-Name, wird das entsprechende Skript upgedated.
Man kann sich aber durch das nachfolgende Agenten-Skript „IPS2Beitrag_SkriptAgent.ips.php“ behelfen:
Es wird
- das Agenten-Skript mit dem obigen Skript „IPS2Beitrag_SkriptTransfer.ips.php“ übertragen
- dann entsprechend der Aufforderung des Skriptes (ACHTUNG!!: Remotes Skript … auf PC … muß umbenannt werden ) auf den remoten PCs einmalig umbenennen.
- das Skript „IPS2Beitrag_SkriptTransfer.ips.php“ mit ‚$StarteSkript = 1‘ nochmal ausführen; damit wird/werden die Agenten-Skripte auf den remoten PCs ausgeführt und die darin konfigurierten Kategorien, Variablen, Skripte, Timer, Batchfiles für Linux angelegt.
- die dann noch auf den remoten PCs noch leeren Skripte mit dem obigen Skript „IPS2Beitrag_SkriptTransfer.ips.php“ befüllen (mehrfach mit ‚$StarteSkript = 0‘ und jeweils veränderter Variable $Skript für den Skript-Namen befüllen
<?
/*
* @file IPS2Beitrag_SkriptAgent.ips.php
* @author Harald Hertlein
* @version 21.10.15 17:03
*
* Legt verschiedene Komponenten auf einem (remoten) IPS-System an:
* Kategorien
* Variablen
* Skripte
* Timer
* Batchfiles für Linux
*
*/
$Msg = '';
// ----------------- Konfigurationsanweisungen Start -----
// 1
$KAT = CreateCategory ('Name', 0, 100, 'Ident');
// 1.1
$VIS = CreateVariable ('Variable zur Visualisierung', 3, $KAT, 0, "~HTMLBox", null, '', '', "VIS");
// 1.2
$DTA = CreateVariable ('Variable zur Datenspeicherung', 3, $KAT, 1, "~String", null, '', '', "DTA");
IPS_SetHidden ($DTA, true);
// 1.3
$MON = CreateEmptyScript ('Anzeige-Skript', $KAT, 2, true, 'MON'); // Skript zur Anzeige, Position 2, Hidden
// 1.4
$ACT = CreateEmptyScript ('Ausführungs-Skript', $KAT, 3, true, 'ACT'); // Skript zur Ausführung
// 1.4.1
CreateTimer_CyclicByMinutes('Trigger', $ACT, 8, false); // Timer, noch nicht aktiviert
// 1.4.2 ff
CreateEmptyScript ('Linux', $ACT, 2, false, '', 'sh'); // ein Batchfiles für Linux (Linux.sh)
// ----------------- Konfigurationsanweisungen Ende -----
echo $Msg;
function CreateCategory ($Name, $ParentId = 0, $Position = 0, $ident = "") {
global $Msg;
if ($ident == "")
$ident = Trim_Ident ($Name);
$ObjectId = @IPS_GetObjectIDByIdent ($ident, $ParentId);
if ($ObjectId === false)
$ObjectId = @IPS_GetVariableIDByName ($Name, $ParentId);
if ($ObjectId === false) {
$ObjectId = IPS_CreateCategory ();
IPS_SetName ($ObjectId, $Name);
IPS_SetParent ($ObjectId, $ParentId);
IPS_SetPosition ($ObjectId, $Position);
if ($ident)
IPS_SetIdent ($ObjectId, $ident);
$Msg .= "$ObjectId ist neue Kategory '" . $Name . "' (Ident: " . $ident . ")
";
}
return $ObjectId;
}
/** Quelle IPSInstaller: Anlegen einer Variable (mod.) */
function CreateVariable ($Name, $Type, $ParentId, $Position = 0, $Profile = "", $Action = null, $ValueDefault = '', $Icon = '', $ident = "") {
global $Msg;
if ($ident == "")
$ident = Trim_Ident ($Name);
$ObjectId = @IPS_GetObjectIDByIdent ($ident, $ParentId);
if ($ObjectId === false)
$ObjectId = @IPS_GetVariableIDByName ($Name, $ParentId);
if ($ObjectId === false) {
$ObjectId = IPS_CreateVariable ($Type);
IPS_SetName ($ObjectId, $Name);
IPS_SetIdent ($ObjectId, $ident);
IPS_SetParent ($ObjectId, $ParentId);
IPS_SetPosition ($ObjectId, $Position);
IPS_SetVariableCustomProfile ($ObjectId, $Profile);
IPS_SetVariableCustomAction ($ObjectId, $Action);
IPS_SetIcon ($ObjectId, $Icon);
SetValue ($ObjectId, $ValueDefault);
$Msg .= "$ObjectId ist neue Variable '" . $Name . "' (Ident: " . $ident . ")
";
}
$VariableData = IPS_GetVariable ($ObjectId);
if ($VariableData['VariableCustomProfile'] <> $Profile) {
$Msg .= " VariableProfile '$Profile' für Variable '$Name'
";
IPS_SetVariableCustomProfile ($ObjectId, $Profile);
}
if ($VariableData['VariableCustomAction'] <> $Action) {
$Msg .= " VariableCustomAction '$Action' für Variable '$Name'
";
IPS_SetVariableCustomAction ($ObjectId, $Action);
}
UpdateObjectData ($ObjectId, $Position, $Icon);
return $ObjectId;
}
/** Quelle IPSInstaller: Anlegen eines Scriptes. (mod.) */
function CreateScript ($Name, $File, $ParentId, $Position = 0) {
global $Msg;
$ObjectId = @IPS_GetObjectIDByIdent (Trim_Ident ($Name), $ParentId);
if ($ObjectId === false)
$ObjectId = @IPS_GetScriptIDByName ($Name, $ParentId);
if ($ObjectId === false) {
$ObjectId = IPS_CreateScript (0);
IPS_SetName ($ObjectId, $Name);
IPS_SetIdent ($ObjectId, Trim_Ident ($Name));
if ($File)
IPS_SetScriptFile ($ObjectId, $File);
IPS_SetParent ($ObjectId, $ParentId);
IPS_SetPosition ($ObjectId, $Position);
$Msg .= "$ObjectId ist neues Script '" . $Name . "'
";
}
UpdateObjectData ($ObjectId, $Position);
return $ObjectId;
}
function CreateEmptyScript ($Name, $ParentId, $Position = 0, $Hidden = true, $Ident = '', $Ext = 'ips.php') {
global $Msg;
if (file_exists (IPS_GetKernelDir () . '/scripts/' . $Name . '.' . $Ext)) {
$ObjectId = @IPS_GetObjectIDByIdent ($ident, $ParentId);
if ($ObjectId === false)
$ObjectId = @IPS_GetVariableIDByName ($Name, $ParentId);
return $ObjectId;
}
$ObjectId = CreateScript ($Name, '', $ParentId, $Position);
if ($Ident)
IPS_SetIdent ($ObjectId, $Ident);
rename (IPS_GetKernelDir () . '/scripts/' . IPS_GetScript ($ObjectId)['ScriptFile'], IPS_GetKernelDir () . '/scripts/' . $Name . '.' . $Ext);
IPS_SetScriptFile ($ObjectId, $Name . '.' . $Ext);
IPS_SetHidden ($ObjectId, $Hidden);
$Msg .= " $Name.$Ext (Ident: $Ident)
";
return $ObjectId;
}
/** Quelle IPSInstaller: Definieren "Minuten" Timer */
function CreateTimer_CyclicByMinutes($Name, $ParentId, $Minutes, $Active = true) {
global $Msg;
$ObjectId = @IPS_GetObjectIDByIdent(Trim_Ident($Name), $ParentId);
if ($ObjectId === false)
$ObjectId = @IPS_GetEventIDByName($Name, $ParentId);
if ($ObjectId === false) {
$ObjectId = IPS_CreateEvent(1 /* Cyclic Event */);
IPS_SetName($ObjectId, $Name);
IPS_SetIdent($ObjectId, Trim_Ident($Name));
IPS_SetParent($ObjectId, $ParentId);
if (!IPS_SetEventCyclic($ObjectId, 2 /* Daily */, 1 /* Unused */, 0 /* Unused */, 0/* Unused */, 2/* TimeType Minutes */, $Minutes/* Minutes */)) {
$Msg .= "IPS_SetEventCyclic failed !!!
";
exit;
}
IPS_SetEventActive($ObjectId, $Active);
$Msg .= "$ObjectId ist neuer Timer '" . $Name . "'
";
}
return $ObjectId;
}
/** Quelle IPSInstaller (unzutreffenderweise Get_IdentByName: Ident aus Namen generieren) */
function Trim_Ident ($name) {
$ident = str_replace (' ', '', $name);
$ident = str_replace (array ('ö', 'ä', 'ü', 'Ö', 'Ä', 'Ü'), array ('oe', 'ae', 'ue', 'Oe', 'Ae', 'Ue'), $ident);
$ident = str_replace (array ('"', '\'', '%', '&', '(', ')', '=', '#', '<', '>', '|', '\\'), '', $ident);
$ident = str_replace (array (',', '.', ':', ';', '!', '?'), '', $ident);
$ident = str_replace (array ('+', '-', '/', '*'), '', $ident);
return $ident;
}
// ------------------------------------------------------------------------------------------------
function UpdateObjectData ($ObjectId, $Position, $Icon = "") {
global $Msg;
$ObjectData = IPS_GetObject ($ObjectId);
$ObjectPath = IPS_GetLocation ($ObjectId);
if ($ObjectData['ObjectPosition'] <> $Position and $Position !== false) {
$Msg .= "Set ObjectPosition='$Position' for Object='$ObjectPath'
";
IPS_SetPosition ($ObjectId, $Position);
}
if ($ObjectData['ObjectIcon'] <> $Icon and $Icon !== false) {
$Msg .= "Set ObjectIcon='$Icon' for Object='$ObjectPath'
";
IPS_SetIcon ($ObjectId, $Icon);
}
}
?>
Achtung Falle !!
Wenn man ein auf einem Windows-PC ein für einen Linux-PC vorgesehenes Skript-File (*.sh) erstellt und dorthin überträgt, ist die Wahscheinlichkeit, dass es auf dem Linux-PC nicht korrekt abläuft, ziemlich hoch.
Grund: Die Text-Formate von Microsoft und dem Rest der Welt sind unterschiedlich und die Bash-Shell von Linux repariert das leider nicht!
Deshalb muß ein mit der obigen Methode übertragene Nicht-PHP-File auf dem Linux-PC „nachbearbeitet“ werden. Am besten geht das m.E. mit dem Tool Dos2Unix, das man sich folgendermaßen unter Linux installiert:
$ sudo apt-get install dos2unix
Auf neueren Windows-Systemen ist das Tool leider nicht installierbar.
Auch Text-Dateien (z.B. CRON-JOB Listen), die für Linux auf einem Windows-PC erstellt worden sind, müssen so nachbearbeitet werden!
Viel Spaß
Harald