Hallo,
ich habe die Überprüfung in include/require mit eingebaut.
Ich habe das Script nochmal komplett umgebaut, um die Ermittlung der Fehler/Warnungen/Informationen von der Ausgabe zu trennen.
Alexa habe ich nicht mit eingebaut, da ich keine Alex-Instanz habe, kann ich das auch nicht testen.
Die explizite Prüfung des WebHook ist nicht mehr drin, das ist aber, weil bei den Instanz-Referenzen auch der WebHook betrachtet wird.
<?php
declare(strict_types=1);
// ID einer Stringvariablen mit Profil ~HTML-Box
$htmlString = xxxxx;
// ID einer Integervariablen für Fehleranzahl
$checkErrorCount = xxxxx;
// ID einer Intergervariablen mit Profil ~UnixTimeStamp
$kernelStart = xxxxx;
// SMTP Instanz, falls Mail erwünscht
$smptID = 0;
// Kommentar mit Schlüsselwort, der besagt, das in dieser Zeile eines Scriptes ID's nicht auf Gülrigkeit geprüft werden sollen
$no_id_check = '/*NO_ID_CHECK*/';
// zu ignorierende Objekt-IDs
$ignoreIDs = [];
static $SymconHealth_Info = 0;
static $SymconHealth_Warn = 1;
static $SymconHealth_Error = 2;
function addEnt(&$lst, $tag, $id, $msg, $lvl)
{
$entV = isset($lst[$tag]) ? $lst[$tag] : [];
$entV[] = [
'ID' => $id,
'Msg' => $msg,
'Level' => $lvl,
];
$lst[$tag] = $entV;
}
$startTime = IPS_GetKernelStartTime();
$now = time();
// Threads
$threadList = IPS_GetScriptThreadList();
$threadCount = 0;
foreach ($threadList as $t => $i) {
$thread = IPS_GetScriptThread($i);
$ScriptID = $thread['ScriptID'];
if ($ScriptID != 0) {
$threadCount++;
}
}
// Timer
$timerCount = 0;
$timer1MinCount = 0;
$timer5MinCount = 0;
$timerList = IPS_GetTimerList();
foreach ($timerList as $t) {
$timer = IPS_GetTimer($t);
$next_run = $timer['NextRun'];
if ($next_run == 0) {
continue;
}
$timerCount++;
$delay = $next_run - $now;
if ($delay < 60) {
$timer1MinCount++;
} elseif ($delay < 300) {
$timer5MinCount++;
}
}
$errorList = [];
// Objekte
$objectList = IPS_GetObjectList();
$objectCount = count($objectList);
foreach ($objectList as $objectID) {
if (in_array($objectID, $ignoreIDs)) {
continue;
}
$object = IPS_GetObject($objectID);
$parentID = $object['ParentID'];
if ($parentID != 0 && !IPS_ObjectExists($parentID)) {
addEnt($errorList, 'Objekte', $objectectID, 'übergeordnetes Objekt mit ID ' . $parentID . ' ist unbekannt', $SymconHealth_Error);
}
$childrenIDs = $object['ChildrenIDs'];
$badIDs = [];
foreach ($childrenIDs as $childrenID) {
if (!IPS_ObjectExists($childrenID)) {
addEnt($errorList, 'Objekte', $objectID, 'untergeordnetes Objekt mit ID ' . $childrenID . ' ist unbekannt', $SymconHealth_Error);
}
}
}
// Links
$linkList = IPS_GetLinkList();
$linkCount = count($linkList);
foreach ($linkList as $linkID) {
$link = IPS_GetLink($linkID);
$targetID = $link['TargetID'];
if (!IPS_ObjectExists($targetID)) {
addEnt($errorList, 'Links', $linkID, 'Ziel-Objekt mit ID ' . $targetID . ' ist unbekannt', $SymconHealth_Error);
}
}
// Module
$moduleList = IPS_GetModuleList();
$moduleCount = count($moduleList);
// Kategorien
$categoryList = IPS_GetCategoryList();
$categoryCount = count($categoryList);
// Instanzen
$instanceStatusCodes = [
101 => 'Instanz wird erstellt',
102 => 'Instanz ist aktiv',
103 => 'Instanz wird gelöscht',
104 => 'Instanz ist inaktiv',
105 => 'Instanz wurde nicht erzeugt',
];
$instanceList = IPS_GetInstanceList();
$instanceCount = count($instanceList);
foreach ($instanceList as $instanceID) {
if (in_array($instanceID, $ignoreIDs)) {
continue;
}
$instance = IPS_GetInstance($instanceID);
$instanceStatus = $instance['InstanceStatus'];
if (in_array($instanceStatus, [102])) {
continue;
}
if (isset($instanceStatusCodes[$instanceStatus])) {
$msg = $instanceStatusCodes[$instanceStatus];
if (in_array($instanceStatus, [104])) {
$lvl = $SymconHealth_Info;
} else {
$lvl = $SymconHealth_Warn;
}
} else {
$msg = 'Status ' . $instanceStatus;
$lvl = $SymconHealth_Error;
}
addEnt($errorList, 'Instanzen', $instanceID, $msg, $lvl);
}
// Referenzen der Instanzen
foreach ($instanceList as $instanceID) {
if (in_array($instanceID, $ignoreIDs)) {
continue;
}
$refIDs = IPS_GetReferenceList($instanceID);
foreach ($refIDs as $refID) {
if (!IPS_ObjectExists($refID)) {
addEnt($errorList, 'Instanzen', $instanceID, 'referenziertes Objekt mit ID ' . $refID . ' ist unbekannt', $SymconHealth_Error);
}
}
}
// Scripte
$fileListIPS = [];
$fileListSYS = [];
$fileListINC = [];
$scriptList = IPS_GetScriptList();
$scriptCount = count($scriptList);
foreach ($scriptList as $scriptID) {
$script = IPS_GetScript($scriptID);
$fileListIPS[] = $script['ScriptFile'];
if (in_array($scriptID, $ignoreIDs)) {
continue;
}
if ($script['ScriptIsBroken']) {
addEnt($errorList, 'Scripte', $scriptID, 'ist fehlerhaft', $SymconHealth_Error);
}
}
// Script im Filesystem
$path = IPS_GetKernelDir() . 'scripts';
$handle = opendir($path);
while ($file = readdir($handle)) {
if (!is_file($file)) {
continue;
}
if (!preg_match('/^.*\.php$/', $file)) {
continue;
}
if (preg_match('/^.*\.inc\.php$/', $file)) {
continue;
}
$fileListSYS[] = $file;
}
closedir($handle);
foreach ($fileListIPS as $file) {
$text = @file_get_contents($file);
if ($text == false) {
continue;
}
$scriptID = @IPS_GetScriptIDByFile($file);
if (in_array($scriptID, $ignoreIDs)) {
continue;
}
$lines = explode(PHP_EOL, $text);
foreach ($lines as $line) {
if (preg_match('/' . preg_quote($no_id_check, '/') . '/', $line)) {
continue;
}
if (preg_match('/^[\t ]*(require_once|require|include_once|include)[\t ]*\([\t ]*(.*)[\t ]*\)[\t ]*;/', $line, $r)) {
$a = $r[2];
} elseif (preg_match('/^[\t ]*(require_once|require|include_once|include)[\t ]*(.*)[\t ]*;/', $line, $r)) {
$a = $r[2];
} else {
continue;
}
if (preg_match('/^[\t ]*[\'"]([^\'"]*)[\'"][\t ]*$/', $a, $x)) {
$inc = $x[1];
if (!in_array($inc, $fileListINC)) {
$fileListINC[] = $inc;
}
if (in_array($inc, $fileListIPS)) {
continue;
}
if (file_exists($inc)) {
continue;
}
addEnt($errorList, 'Scripte', $scriptID, 'Datei "' . $inc . '" fehlt', $SymconHealth_Error);
} elseif (preg_match('/IPS_GetScriptFile[\t ]*\([\t ]*([0-9]{5})[\t ]*\)/', $a, $x)) {
$id = $x[1];
$inc = @IPS_GetScriptFile($id);
if ($inc == false) {
addEnt($errorList, 'Scripte', $scriptID, 'Script mit ID ' . $id . ' ist nicht vorhanden', $SymconHealth_Error);
} else {
if (!in_array($inc, $fileListINC)) {
$fileListINC[] = $inc;
}
}
} else {
// echo 'a=' . $a . '=' . PHP_EOL;
}
}
}
// überflüssige Scripte
$scriptError = 0;
foreach ($fileListSYS as $file) {
if (in_array($file, $fileListIPS) || in_array($file, $fileListINC)) {
continue;
}
addEnt($errorList, 'Scripte', 0, 'Datei "' . $file . '" ist überflüssig', $SymconHealth_Info);
}
// fehlende Scripte
$scriptError = 0;
foreach ($scriptList as $scriptID) {
if (in_array($scriptID, $ignoreIDs)) {
continue;
}
$script = IPS_GetScript($scriptID);
$file = $script['ScriptFile'];
if (in_array($file, $fileListSYS)) {
continue;
}
addEnt($errorList, 'Scripte', $scriptID, 'Datei "' . $file . '" fehlt', $SymconHealth_Error);
}
// Objekt-ID's in Scripten
foreach ($fileListSYS as $file) {
if (!in_array($file, $fileListIPS)) {
continue;
}
$text = @file_get_contents($file);
if ($text == false) {
continue;
}
$scriptID = @IPS_GetScriptIDByFile($file);
if (in_array($scriptID, $ignoreIDs)) {
continue;
}
$lines = explode(PHP_EOL, $text);
foreach ($lines as $line) {
if (preg_match('/' . preg_quote($no_id_check, '/') . '/', $line)) {
continue;
}
if (preg_match('/[^!=><]=[\t ]*([0-9]{5})[^0-9]/', $line, $r)) {
$id = $r[1];
} elseif (preg_match('/\([\t ]*([0-9]{5})[^0-9]/', $line, $r)) {
$id = $r[1];
} else {
continue;
}
if (!in_array($id, $objectList)) {
addEnt($errorList, 'Scripte', $scriptID, 'Objekt mit ID ' . $id . ' ist unbekannt', $SymconHealth_Error);
}
}
}
// Events
$eventList = IPS_GetEventList();
$eventCount = count($eventList);
$eventActive = 0;
foreach ($eventList as $eventID) {
if (in_array($eventID, $ignoreIDs)) {
continue;
}
$event = IPS_GetEvent($eventID);
$active = $event['EventActive'];
if ($active) {
$eventActive++;
}
$err = 0;
$varID = $event['TriggerVariableID'];
if ($varID != 0 && IPS_ObjectExists($varID) == false) {
addEnt($errorList, 'Ereignisse', $eventID, 'auslösende Variable ' . $varID . ' ist unbekannt', $SymconHealth_Error);
}
$eventConditions = $event['EventConditions'];
foreach ($eventConditions as $eventCondition) {
$variableRules = $eventCondition['VariableRules'];
foreach ($variableRules as $variableRule) {
$varID = $variableRule['VariableID'];
if ($varID != 0 && IPS_ObjectExists($varID) == false) {
addEnt($errorList, 'Ereignisse', $eventID, 'Bedingungs-Variable ' . $varID . ' ist unbekannt', $SymconHealth_Error);
}
}
}
}
// Variablen
$variableList = IPS_GetVariableList();
$variableCount = count($variableList);
foreach ($variableList as $variableID) {
if (in_array($variableID, $ignoreIDs)) {
continue;
}
$variable = IPS_GetVariable($variableID);
// Variablenprofile
$variableProfile = $variable['VariableProfile'];
if ($variableProfile != false && IPS_GetVariableProfile($variableProfile) == false) {
addEnt($errorList, 'Variablen', $variableID, 'Standardprofil "' . $variableProfile . '" ist unbekannt', $SymconHealth_Error);
}
$variableCustomProfile = $variable['VariableCustomProfile'];
if ($variableCustomProfile != false && IPS_GetVariableProfile($variableCustomProfile) == false) {
addEnt($errorList, 'Variablen', $variableID, 'Benutzerprofil "' . $variableCustomProfile . '" ist unbekannt', $SymconHealth_Error);
}
// Variableaktionen
$variableAction = $variable['VariableAction'];
if ($variableAction > 0 && !IPS_ObjectExists($variableAction)) {
addEnt($errorList, 'Variablen', $variableID, 'Standardaktion ' . $variableAction . '" ist unbekannt', $SymconHealth_Error);
}
$variableCustomAction = $variable['VariableCustomAction'];
if ($variableCustomAction > 1 && !IPS_ObjectExists($variableCustomAction)) {
addEnt($errorList, 'Variablen', $variableID, 'Benutzeraktion ' . $variableCustomAction . '" ist unbekannt', $SymconHealth_Error);
}
}
// Medien
$path = IPS_GetKernelDir();
$mediaList = IPS_GetMediaList();
$mediaCount = count($mediaList);
foreach ($mediaList as $mediaID) {
if (in_array($mediaID, $ignoreIDs)) {
continue;
}
$media = IPS_GetMedia($mediaID);
if ($media['MediaType'] == 3 /* Stream */) {
continue;
}
$file = $media['MediaFile'];
if (file_exists($path . $file)) {
continue;
}
if ($media['MediaIsCached']) {
addEnt($errorList, 'Medien', $mediaID, 'ist noch nicht gespeichert', $SymconHealth_Warn);
} else {
addEnt($errorList, 'Medien', $mediaID, 'Datei "' . $file . '" fehlt', $SymconHealth_Error);
}
}
// HTML-Text aufbauen
$errorText = '';
$errorTotal = 0;
foreach ($errorList as $tag => $errEntries) {
$errorText .= '<b>' . $tag . ':</b><br>' . PHP_EOL;
foreach ($errEntries as $err) {
$lvl = $err['Level'];
switch ($lvl) {
case $SymconHealth_Info:
$col = 'grey';
break;
case $SymconHealth_Warn:
$col = 'yellow';
break;
case $SymconHealth_Error:
default:
$col = 'red';
$errorTotal++;
break;
}
$errorText .= '<span style="color: ' . $col . ';"> ';
$id = $err['ID'];
if ($id != 0) {
$errorText .= '#' . $id;
$loc = @IPS_GetLocation($id);
if ($loc != false) {
$errorText .= '(' . $loc . ')';
}
$errorText .= ': ';
}
$errorText .= $err['Msg'];
$errorText .= '</span><br>' . PHP_EOL;
}
$errorText .= '<br>' . PHP_EOL;
}
$html = '';
$html .= '<head>' . PHP_EOL;
$html .= '<style>' . PHP_EOL;
$html .= 'body { margin: 1; padding: 0; font-family: "Open Sans", sans-serif; font-size: 16px; }' . PHP_EOL;
$html .= 'table { border-collapse: collapse; border: 0px solid; margin: 0.5em;}' . PHP_EOL;
$html .= 'th, td { padding: 1; }' . PHP_EOL;
$html .= 'thead, tdata { text-align: left; }' . PHP_EOL;
$html .= '#spalte_title { width: 160px; }' . PHP_EOL;
$html .= '#spalte_value { }' . PHP_EOL;
$html .= '</style>' . PHP_EOL;
$html .= '</head>' . PHP_EOL;
$html .= '<body>' . PHP_EOL;
$html .= '<table>' . PHP_EOL;
$html .= '<colgroup><col id="spalte_title"></colgroup>' . PHP_EOL;
$html .= '<colgroup><col id="spalte_value"></colgroup>' . PHP_EOL;
$html .= '<tr><td>Stand</td><td>' . date('d.m.Y H:i:s', $now) . '<br></td></tr>' . PHP_EOL;
$html .= '<tr><td>Kategorien</td><td>' . $categoryCount . '</td></tr>' . PHP_EOL;
$html .= '<tr><td>Objekte</td><td>' . $objectCount . '</td></tr>' . PHP_EOL;
$html .= '<tr><td>Links</td><td>' . $linkCount . '</td></tr>' . PHP_EOL;
$html .= '<tr><td>Module</td><td>' . $moduleCount . '</td></tr>' . PHP_EOL;
$html .= '<tr><td>Instanzen</td><td>' . $instanceCount . '</td></tr>' . PHP_EOL;
$html .= '<tr><td>Scripte</td><td>' . $scriptCount . '</td></tr>' . PHP_EOL;
$html .= '<tr><td>Variablen</td><td>' . $variableCount . '</td></tr>' . PHP_EOL;
$html .= '<tr><td>Medien</td><td>' . $mediaCount . '</td></tr>' . PHP_EOL;
$html .= '<tr><td>Ereignisse</td><td>' . $eventCount . ' (aktiv=' . $eventActive . ')</td></tr>' . PHP_EOL;
$html .= '<tr><td>Timer</td><td>' . $timerCount . ' (1m=' . $timer1MinCount . ', 5m=' . $timer5MinCount . ')</td></tr>' . PHP_EOL;
$html .= '<tr><td>Threads</td><td>' . $threadCount . '</td></tr>' . PHP_EOL;
$html .= '</table>' . PHP_EOL;
if ($errorText == '') {
$html .= '<br>keine Meldungen<br>' . PHP_EOL;
} else {
$html .= $errorText;
}
$html .= '</body>' . PHP_EOL;
SetValueString($htmlString, $html);
SetValueInteger($kernelStart, $startTime);
SetValueInteger($checkErrorCount, $errorTotal);
if ($errorTotal > 0 && $smptID != false) {
// Mail-Text aufbauen
$mailText = '';
foreach ($errorList as $tag => $errEntries) {
foreach ($errEntries as $err) {
$lvl = $err['Level'];
if ($lvl == $SymconHealth_Error) {
$id = $err['ID'];
if ($id != 0) {
$mailText .= '#' . $id;
$loc = @IPS_GetLocation($id);
if ($loc != false) {
$mailText .= '(' . $loc . ')';
}
$mailText .= ': ';
}
$mailText .= $err['Msg'];
$mailText .= PHP_EOL;
}
}
$errorText .= PHP_EOL;
}
SMTP_SendMail($smptID, 'IPS-Check', $mailText);
}