Statusvariablen-Log fürs WebFront

Ich benutze an vielen Stellen numerische Variablen, die einen Status repräsentieren. Beispielsweise:

shot.jpg

Auch Geräte wie z.B. HomeMatic-Fenstergriffe nutzen Variablenprofile mit Zuordnungen zu bestimmten Werten.

Die Statusänderungen solcher Variablen möchte ich gerne loggen - was in IPS ja grundsätzlich sehr einfach ist. Leider sieht das im WebFront aber in der Graphenansicht ziemlich schräg aus: Die aggregierten Werte bilden eine hübsche, abgerundete Kurve, was aber für eine Statusvariable wie diese wenig Sinn ergibt.

Was ich eigentlich möchte, ist ein Text-Log, also eine bestimmte Anzahl an jüngsten Ereignissen, jeweils mit Datum/Uhrzeit der Statusänderung. Und da der numerische Wert visuell irrelevant ist, möchte ich am liebsten nur die Texte in der entsprechenden Farbe angezeigt haben. Ungefähr so:

shot2.png

Und genau dafür habe ich ein Skript geschrieben, das vielleicht auch anderen nützt! :slight_smile:

Es erzeugt ein Logfeld automatisch aus den letzten n aufgezeichneten Änderungen aller Variablen, die oben in die Liste eingetragen werden.

<?
// This is the list of variables you wish to display log fields for. Keys are
// variable ids to log, values are either:
//
// - the maximum number of entries to display in a log field for only this variable
// - the identifier of a shared log field defined in the $shared_logs_list
// - or an associative array containing the following keys:
//   "single_log_size" - number of entries for single variable log (same effect
//     as only supplying a number as the value of the list entry (see above)
//   "shared_log" - identifier of a shared log field. The same identifier must
//     exist as an entry in the $shared_logs_list, where further parameters of
//     the shared log field are supplied.
//   "name" - pretty name to display in shared log field (not used in single log
//     fields, as there is no such column in them!)
//   "display_old_value" - whether to display the old value in shared log field
//     entries for this variable
//
$var_list = array(
		54064 /*[Hardware-Instanzen\Geräte\Schneeballmaschine\Gerätestatus]*/ => 25,
		14404 /*[Hardware-Instanzen\HomeMatic\Heizkörper\Heizkörper Bad\CLIMATECONTROL_VENT_DRIVE\VALVE_STATE]*/ => array(
			"shared_log" => "test",
			"name" => "Heizkörper Bad"
		),
		46290 /*[Hardware-Instanzen\HomeMatic\Heizkörper\Heizkörper Büro\CLIMATECONTROL_VENT_DRIVE\VALVE_STATE]*/ => array(
			"shared_log" => "test",
			"name" => "Heizkörper Büro"
		),
		38132 /*[Hardware-Instanzen\HomeMatic\Heizkörper\Heizkörper Eingangszimmer\CLIMATECONTROL_VENT_DRIVE\VALVE_STATE]*/ => array(
			"shared_log" => "test",
			"name" => "Heizkörper Eingang"
		),
		47435 /*[Hardware-Instanzen\HomeMatic\Heizkörper\Heizkörper Kino\CLIMATECONTROL_VENT_DRIVE\VALVE_STATE]*/ => array(
			"shared_log" => "test",
			"name" => "Heizkörper Kino"
		),
		18727 /*[Hardware-Instanzen\HomeMatic\Heizkörper\Heizkörper Schlafzimmer\CLIMATECONTROL_VENT_DRIVE\VALVE_STATE]*/ => array(
			"shared_log" => "test",
			"name" => "Heizkörper Schlafzimmer"
		),
		38565 /*[Konfiguration und Software-Instanzen\Heizung\Therme\eBus Manager\Heizung\Status\Fehlerstatus]*/ => array(
			"shared_log" => "test",
			"name" => "Heizungstherme"
		),
		54982 /*[Skripte\IO-Boxen\HWR\Register Variable für IO-Box HWR\Auswerteskript\Heizung Stufe]*/ => array(
			"shared_log" => "test",
			"name" => "Modulation",
			"display_old_value" => false
		),
);

// This list contains parameters for shared log fields. Every such field must have
// an entry here. Keys are the identifiers of the fields defined, values are:
//
// - a number representing the maximum number of entries, or
// - an associative array containing the following keys:
//   "log_size" - number of entries, same effect as supplying a number only
// (may be enhanced in future versions of this script!)
//
$shared_logs_list = array(
	"test" => 25
);

// After editing the lists, please execute the script in order to apply changes!

////////////////////////////////////////////////////////////////////////////////
// nothing needs to be edited below this line!

// determine whether the script is run manually in the console, in which case
// some debug output is generated and variable ids removed from the list will
// also have the corresponding events and fields removed
$debug = $_IPS['SENDER'] == 'Execute';

// retrieve id of archive control
$ac_id = IPS_GetInstanceListByModuleID('{43192F0B-135B-4CE7-A0A7-1475603F3060}')[0];

// remove log field and event for variables that have been removed from the list
if($debug) { // only when executing the script in the console!
	$children = IPS_GetChildrenIDs($_IPS['SELF']);
	foreach($children as $id) {
		$event = @IPS_GetEvent($id);
		if($event !== false && $event['EventType'] == 0) { // remove single variable log and variable event...
			$var_id = $event['TriggerVariableID'];
			if(!array_key_exists($var_id, $var_list)) {
				echo "Removing logging for variable \"" . @IPS_GetName($var_id) . "\" (ID " . $var_id . ")!\r";
				remove_var_event($var_id);
				remove_single_log_field($var_id);
			}
		} else { // remove shared log fields...
			$link = @IPS_GetLink($id);
			if($link !== false) {
				$field_id = $link['TargetID'];
				$obj = IPS_GetObject($id);
				$ident = $obj['ObjectIdent'];
				if(substr($ident, 0, 24) == 'StateVarLog_SharedField_') {
					$log_name = substr($ident, 24);
					if(!array_key_exists($log_name, $shared_logs_list)) {
						echo "Removing shared log field \"" . $log_name . "\"!\r";
						remove_shared_log_field($log_name);
					}
				}
			}
		}
	}
}

// array to hold history lists for shared log fields
$shared_history = array();

// cache for variable profiles
$profiles = array();

// process the variable list
foreach($var_list as $id => $parameters) {
	if($_IPS['SENDER'] == 'Variable') {
		if($id != $_IPS['VARIABLE'] && !have_shared_log($id, $_IPS['VARIABLE'])) continue;
	}
	
	$var = @IPS_GetVariable($id);
	
	if($var === false) { // check if variable found
		if($debug) echo "Variable with ID " . $id . " not found!\r";
		remove_var_event($id);
		remove_single_log_field($id);
		continue;
	}
	
	// allow a numeric value instead of an associative array to easily specify
	// the number of entries for a single variable log. For advanced parameters,
	// such as shared multiple variable logs an associative array has to be used.
	if(!is_array($parameters)) {
		if(is_int($parameters)) { // most simple case - single variable log with n entries
			$parameters = array("single_log_size" => $parameters);
		} else if(is_string($parameters)) {
			$parameters = array("shared_log" => $parameters);
		} else {
			if($debug) echo "Invalid parameter for variable \"" . @IPS_GetName($var_id) . "\"!\r";
			continue;
		}
	}
	
	ensure_var_event($id); // ensure there is an event for this variable
	$var_name = IPS_GetName($id);
	
	// if the type of the variable supports profiles with associations, try to
	// retrieve the association list so that log entries can be created with
	// text and color, rather than just bare values.
	$profile = false;
	$prof_name = $var['VariableCustomProfile'];
	if($prof_name == '') $prof_name = $var['VariableProfile'];
	
	if($prof_name != '') {
		if(!array_key_exists($prof_name, $profiles)) {
			$profile = @IPS_GetVariableProfile($prof_name);
			
			if($profile === false) {
				if($debug) echo "Profile \"" . $prof_name . "\" not found!\r";
			} else {
				$profiles[$prof_name] = $profile;
			}
		} else {
			$profile = $profiles[$prof_name];
		}
	}
	
	// logging must be activated for this variable in the archive control, make sure it is
	if(!AC_GetLoggingStatus($ac_id, $id)) {
		AC_SetLoggingStatus($ac_id, $id, true);
		IPS_ApplyChanges($ac_id);
	}
	// displaying a graph doesn't make much sense for variables that represent a
	// status, so disable graph display in the webfront for this variable
	if(AC_GetGraphStatus($ac_id, $id) && $profile !== false && count($profile["Associations"]) > 0) {
		AC_SetGraphStatus($ac_id, $id, false);
		IPS_ApplyChanges($ac_id);
	}
	
	// create and/or update single variable log, if so desired for this variable id
	if(array_key_exists('single_log_size', $parameters) && $parameters['single_log_size'] > 0) {
		// retrieve variable change history entries from archive control
		$var_history = AC_GetLoggedValues($ac_id, $id, 0, 0, $parameters['single_log_size']);
		
		$log_id = ensure_single_log_field($id); // ensure a log field exists for this variable and get its id
		
		// construct the html content for this log
		$log_content = generate_log($var_history, $prof_name);
		if($debug) echo $var_name . " Single Log:\r" . $log_content . "\r";
		SetValue($log_id, $log_content); // write into log field
	} else { // if no single log is desired, remove the log field
		remove_single_log_field($id);
	}
	
	// if this variable should be in a shared log
	if(array_key_exists('shared_log', $parameters)) {
		$log_name = $parameters['shared_log'];
		
		if(array_key_exists($log_name, $shared_logs_list)) {
			// allow for simplified $shared_logs_list structure - if an entries' value
			// is numeric, assume that it's the log's size.
			if(is_int($shared_logs_list[$log_name])) {
				$shared_logs_list[$log_name] = array("log_size" => $shared_logs_list[$log_name]);
			}
			
			// ensure a shared history array for this shared log exists
			if(!array_key_exists($log_name, $shared_history)) $shared_history[$log_name] = array();
			
			if(is_array($shared_logs_list[$log_name])) { // if log exists
				$log_size = $shared_logs_list[$log_name]["log_size"];
				
				// name of the entry will be variable name, or custom name if specified
				// within the variable list entries' parameters
				$name = $var_name;
				if(array_key_exists('name', $parameters)) $name = $parameters['name'];
				
				// determine whether to display the old value in the shared log. This
				// is enabled by default for numeric variables.
				$display_old_value = $var['VariableType'] != 3;
				if(array_key_exists("display_old_value", $parameters)) {
					$display_old_value = $parameters["display_old_value"];
				}

                $ok_value_used = false;
				if(array_key_exists("ok_value", $parameters)) {
					$ok_value = $parameters["ok_value"];
                    $ok_value_used = true;
				}
				
				$var_history = AC_GetLoggedValues($ac_id, $id, 0, 0, $log_size + 1);
				foreach($var_history as $vhindex => $var_hist_entry_original) {
					if($vhindex == $log_size) break;
					$var_hist_entry = array(
						"VariableId" => $id,
						"ProfileName" => $prof_name,
						"Name" => $name,
						"TimeStamp" => $var_hist_entry_original["TimeStamp"],
						"Value" => $var_hist_entry_original["Value"],
					);
					if($vhindex + 1 < count($var_history) && $display_old_value) {
						$var_hist_entry["OldValue"] = $var_history[$vhindex + 1]["Value"];
					}
                    if($ok_value_used) {
                        $var_hist_entry["FaultState"] = $var_hist_entry["Value"] != $ok_value;
                    }
						
					$inserted = false;
					foreach($shared_history[$log_name] as $shindex => $shared_hist_entry) {
						if($var_hist_entry['TimeStamp'] > $shared_hist_entry['TimeStamp']) {
							array_splice($shared_history[$log_name], $shindex, 0, array($var_hist_entry));
							$inserted = true;
							break;
						}
					}
					if(!$inserted) array_push($shared_history[$log_name], $var_hist_entry);
					if(count($shared_history[$log_name]) > $log_size) array_pop($shared_history[$log_name]);
				}
			}
		} else { // if shared log name not found in $shared_logs_list
			if($debug) echo "Shared log \"" . $log_name . "\" not defined in shared logs list!\r";
		}
	}
}

foreach($shared_logs_list as $log_name => $parameters) {
	if(!is_array($parameters)) continue;
	if(!array_key_exists("log_size", $parameters)) continue;
	if(!array_key_exists($log_name, $shared_history)) continue;
	
	if($parameters['log_size'] <= 0) continue;
	
	$log_id = ensure_shared_log_field($log_name);
	
	// construct the html content for this log
	$log_content = generate_log($shared_history[$log_name]);
	if($debug) echo "Shared Log \"" . $log_name . "\":\r" . $log_content . "\r";
	SetValue($log_id, $log_content); // write into log field
}

// generate log as an html table string
function generate_log($history, $prof_name = "") {
	$result = '<table cellspacing=5 cellpadding=1>';
	foreach($history as $hist_entry) {
		$ts = $hist_entry['TimeStamp'];
		$val = $hist_entry['Value'];
		$time_str = date('j.n.y H:i:s', $ts);
		
		if(array_key_exists("ProfileName", $hist_entry)) {
			$prof_name = $hist_entry["ProfileName"];
		}
		
		$log_entry_str = '<tr><td>' . $time_str . "\t</td>";
        $name_colour_string = "aaaaaa";
		if(array_key_exists("FaultState", $hist_entry)) {
            $name_colour_string = $hist_entry["FaultState"] ? "ff0000" : "00ff00";
        }
		if(array_key_exists("Name", $hist_entry)) {
			$log_entry_str .= "<td><font color=\"#" . $name_colour_string . "\">" . $hist_entry["Name"] . "\t</font></td>";
		}
		if(array_key_exists("OldValue", $hist_entry)) {
			$old_val = $hist_entry["OldValue"];
			//print_r($old_val);
			$log_entry_str .= format_value($old_val, $prof_name) . "<td>&rarr;</td>";
			$colspan = 1;
		} else {
			$colspan = 3;
		}
		$log_entry_str .= format_value($val, $prof_name, $colspan);
		//if($colspan == 1) $log_entry_str .= "<td align=\"left\">&nbsp;</td>";
		$log_entry_str .= "</tr>\r";
		$result .= $log_entry_str;
	}
	$result .= '</table>';
	return $result;
}

function format_value($val, $prof_name, $colspan = 1) {
	global $profiles;
	
	$color_str = "ffffff";
	$align = is_string($val) ? "left" : "right";
	$val_str = htmlentities($val);
	
	if(array_key_exists($prof_name, $profiles)) {
		$profile = $profiles[$prof_name];
		$val_str = $profile['Prefix'] . $val_str . trim($profile['Suffix']);
		$assocs = $profile['Associations'];
		$lastAssocVal = false;
		foreach($assocs as $assoc) { // if associations array supplied, use it to display colorful text rather than bare values!
			if($val >= $assoc['Value'] && ($lastAssocVal === false || $assoc['Value'] > $lastAssocVal)) {
				$lastAssocVal = $assoc['Value'];
				$val_str = sprintf($assoc['Name'], $val);
				$color_str = str_pad(dechex($assoc['Color']), 6, '0', STR_PAD_LEFT);
				$align = "left";
			}
		}
	}
	
	return "<td colspan=\"" . $colspan . "\"><div align=\"". $align . "\"><font color=\"#" . $color_str . "\">" . $val_str . "</font></div></td>";
}

function ensure_shared_log_field($log_name) {
	$ident = 'StateVarLog_SharedField_' . $log_name;
	
	// try to retrieve link to the log field for this variable
	$log_link_id = @IPS_GetObjectIDByIdent($ident, $_IPS['SELF']);
	
	if($log_link_id === false) {
		$log_id = @IPS_GetObjectIDByIdent($ident, IPS_GetParent($_IPS['SELF']));
	} else {
		// normally we get the log field's id by following the link
		$log_id = IPS_GetLink($log_link_id)['TargetID'];
	}
	
	if($log_id === false) {
		$log_id = IPS_CreateVariable(3);
		IPS_SetName($log_id, 'Shared Log ' . $log_name);
		IPS_SetParent($log_id, IPS_GetParent($_IPS['SELF']));
		IPS_SetIdent($log_id, $ident);
		IPS_SetVariableCustomProfile($log_id, '~HTMLBox');
	}
	
	// if no link to the log field exists, create one
	if($log_link_id === false) {
		$log_link_id = IPS_CreateLink();
		IPS_SetParent($log_link_id, $_IPS['SELF']);
		IPS_SetIdent($log_link_id, $ident);
	}
	@IPS_SetLinkTargetID($log_link_id, $log_id);
	
	return $log_id;
}

// remove shared log with the given log name
function remove_shared_log_field($log_name) {
	$ident = 'StateVarLog_SharedField_' . $log_name;
	$log_link_id = @IPS_GetObjectIDByIdent($ident, $_IPS['SELF']);
	
	if($log_link_id !== false) {
		$log_id = IPS_GetLink($log_link_id)['TargetID'];
		if($log_id !== false) IPS_DeleteVariable($log_id);
		IPS_DeleteLink($log_link_id);
	}
}

// Ensure a log field, as well as a link to it exist for the specified variable
// id. The link serves as a reference in case the log field gets moved around.
function ensure_single_log_field($var_id) {
	$ident = 'StateVarLog_Field_' . $var_id;
	
	// try to retrieve link to the log field for this variable
	$log_link_id = @IPS_GetObjectIDByIdent($ident, $_IPS['SELF']);
	
	if($log_link_id === false) {
		// if no link exists, we still try to retrieve the potential log field from
		// below the same parent as the variable - just to make this script a bit
		// more robust in case the link got manually deleted.
		$log_id = @IPS_GetObjectIDByIdent($ident, IPS_GetParent($var_id));
	} else {
		// normally we get the log field's id by following the link
		$log_id = IPS_GetLink($log_link_id)['TargetID'];
	}
	
	if($log_id === false) {
		// get the sorting position of the variable, so that the log field can be
		// put in the same position by default
		$pos = IPS_GetObject($var_id)['ObjectPosition'];
		
		$log_id = IPS_CreateVariable(3);
		IPS_SetName($log_id, IPS_GetName($var_id) . ' Log');
		IPS_SetParent($log_id, IPS_GetParent($var_id));
		IPS_SetIdent($log_id, $ident);
		IPS_SetPosition($log_id, $pos);
		IPS_SetVariableCustomProfile($log_id, '~HTMLBox');
	}
	
	// if no link to the log field exists, create one
	if($log_link_id === false) {
		$log_link_id = IPS_CreateLink();
		IPS_SetParent($log_link_id, $_IPS['SELF']);
		IPS_SetIdent($log_link_id, $ident);
	}
	@IPS_SetLinkTargetID($log_link_id, $log_id);
	
	return $log_id;
}

// Remove log field (and the link to it) for the specified variable id.
function remove_single_log_field($var_id) {
	$ident = 'StateVarLog_Field_' . $var_id;
	$log_link_id = @IPS_GetObjectIDByIdent($ident, $_IPS['SELF']);
	
	if($log_link_id !== false) {
		$log_id = IPS_GetLink($log_link_id)['TargetID'];
		if($log_id !== false) IPS_DeleteVariable($log_id);
		IPS_DeleteLink($log_link_id);
	}
}

// Ensure that a change event exists for the specified variable id, and return
// the event id.
function ensure_var_event($var_id) {
	$ident = 'StateVarLog_Event_' . $var_id;
	
	$event_id = @IPS_GetObjectIDByIdent($ident, $_IPS['SELF']);
	if($event_id === false) {
		$event_id = IPS_CreateEvent(0);
		IPS_SetParent($event_id, $_IPS['SELF']);
		IPS_SetEventTrigger($event_id, 1, $var_id);
		IPS_SetEventActive($event_id, true);
		IPS_SetIdent($event_id, $ident);
	}
	
	return $event_id;
}

// Remove change event for the specified variable id.
function remove_var_event($var_id) {
	$ident = 'StateVarLog_Event_' . $var_id;
	
	$event_id = @IPS_GetObjectIDByIdent($ident, $_IPS['SELF']);
	if($event_id !== false) {
		IPS_DeleteEvent($event_id);
	}
}


// determine whether there is a shared log containing both specified variable ids
function have_shared_log($id1, $id2) {
	global $var_list;
	
	if(!array_key_exists($id1, $var_list)) return false;
	if(!array_key_exists($id2, $var_list)) return false;
	
	$parameters1 = $var_list[$id1];
	$parameters2 = $var_list[$id2];
	
	$shared_log_name_1 = false;
	if(is_string($parameters1)) {
		$shared_log_name_1 = $parameters1;
	} else if(is_array($parameters1) && array_key_exists("shared_log", $parameters1)) {
		$shared_log_name_1 = $parameters1['shared_log'];
	}
	
	$shared_log_name_2 = false;
	if(is_string($parameters2)) {
		$shared_log_name_2 = $parameters2;
	} else if(is_array($parameters2) && array_key_exists("shared_log", $parameters2)) {
		$shared_log_name_2 = $parameters2['shared_log'];
	}
	
	if($shared_log_name_1 === false || $shared_log_name_2 === false) return false;
	
	return $shared_log_name_1 == $shared_log_name_2;
}
?>

Es sollte extrem einfach zu benutzen sein - ihr packt das Skript irgendwo hin, tragt die zu loggenden Variablen in die Liste oben im Skript ein, mit der Anzahl der anzuzeigenden Logeinträge. Das Log-Feld wird an dem gleichen Ort erzeugt, wo die Variable liegt, kann aber beliebig verschoben werden. Falls die Variable bereits archiviert wird, sollten sofort Einträge im Log erscheinen.

Update:
Das Skript unterstützt jetzt auch gemeinsame Logs, in denen die letzten Wertänderungen aus mehreren Variablen auftauchen.

Viel Spaß damit!

Habe ich gleich ausprobiert, gefällt mir. Vielen Dank

Gern :slight_smile:

Stimmt, hatte ich vergessen zu erwähnen - man kann natürlich nicht nur numerische, sondern auch String- und Boolvariablen loggen.

Ich arbeite derzeit an einer erweiterten Version für dieses Skript, die unter anderem erlaubt, mehrere Variablen in einem gemeinsamen Log-Feld anzuzeigen. Beispielsweise wenn man die Zustandsänderungen mehrerer Fenstergriffe o.ä. protokollieren will.

Falls es weitere Anregungen gibt, immer her damit :slight_smile:

Gemeinsame Logs mit mehreren Variablen werden jetzt unterstützt. Die Syntax der Variablenliste, sowie eine neue Liste der gemeinsamen Logs, sind oben im Skript zu sehen und müssen je nach Anwendung mit den zu loggenden Variablen-IDs, sowie ggf. Optionen befüllt werden.

Ein gemeinsames Log sieht dann z.B. so aus:

shot3.jpg

Vielleicht denke ich zu leicht, aber wäre dein erstes Problem nicht einfach damit erledigt gewesen, dass du eine 2. Variable genommen hättest, die gleichzeitig mit dem Variablen-Text beschrieben wird… mit einem Event z.B. und dann „nur“ die 2. Variable geloggt… schon wäre es fertig gewesen…

Ich verstehe nicht, was daran einfacher oder besser sein sollte…? :confused:

Vergleiche 3-Zeiler gegen dein irrsinnig langes Script? :wink:

Falls es einen Dreizeiler gibt, um das selbe zu erreichen, wäre ich aufrichtig beeindruckt. Ehrlich :smiley:

OK, reicht sogar ein 1-Zeiler an Code:

  • [li] 2. Variable vom Typ String anlegen und Logging aktivieren
    [/li][li]Ereignis anlegen: Auslöser „bei Variablenänderung“ -> Variable deine Integer-Variable
    [/li][li]Aktion in Ereignis: Quellcode ausführen -> [/li]php "SetValueString("ID_DER_STRING_VARIABLE",GetValueFormatted( $_IPS['VARIABLE']));

Theoretisch kannst du in die String-Variable sogar mehrere andere Variablen loggen, wenn man die Texte auseinander halten kann, aber schön wäre das nicht.

Hmm, eventuell habe ich mich bei der Beschreibung von Sinn und Zweck meines Skripts zu undeutlich ausgedrückt…?

Was mein Skript tut ist, für eine oder mehrere Variablen deren History („archivierte“ Werte in IPS) als Text-Log zusammenzufassen. Jeweils mit einer spezifizierbaren Anzahl von Einträgen, die neusten zuerst. Dabei wird unter anderem das Variablenprofil angewandt - auf die Werte der History.

Was dein Einzeiler tut: Den aktuellen Wert einer Variablen als formatierten Text in eine zweite vom Typ String zu schreiben.

Edit: Ich habe gerade gesehen, dass es tatsächlich so eine ähnliche Log-Anzeige für archivierte String-Variablen gibt. Das war mir nicht klar.

Allerdings erscheint die nur als Popup anstatt direkt in der Webfront-Oberfläche und ohne farbliche Formatierungen. Mir ging es jetzt auch um eine ansprechende Optik direkt im Webfront.

Aber ja, falls einem das Skript zu umfangreich ist und man mit gewissen optischen Einschränkungen leben kann, ist dein Ansatz auch möglich. Mir persönlich gefallen diese Mini-Logs gut und wem das ebenfalls zusagt, der möge gern auf mein Skript zurückgreifen :slight_smile:

Für mehrere Variablen müsste man den Variablen-Namen mit in die STring-Variable stringen, damit man sie auseinander halten kann. Das Log könnte man auch direkt anzeigen… ich glaube es gab direkt eine Funktion dafür, ansonsten in einer Textbox mit nochmal 2 Zeilen Code. Man kann mit IPS schon ne Menge machen, man muss nur wissen wie.

So sieht das Log halt mit Board-Mitteln aus.
status.PNG

Ich habe es probiert, anscheinend gibt es zwar eine Möglichkeit, Graphen direkt im WF anzuzeigen, aber bei der String-Variablen ging das so nicht. Da erschien einfach ein leerer Graph.

Die zwei Zeilen hätte ich dann aber wirklich gern mal erfahren.

Welche Bordmittel sind das? Ist das ein Webfront-Skin?

Verzeihe bitte die Nachfragen, aber du sagst immer, das geht doch alles viel simpler, aber ohne konkretere Info kann ich schwer beurteilen, ob das am Ende wirklich das gleiche Ergebnis wäre.

Eher sieht es mir danach aus, als sei es dann zwar ähnlich, aber in für mich entscheidenden Punkten eben doch anders.

Ist ja durchaus sinnvoll, wenn du es erwähnst, aber dann bitte auch konkret so dass Leser, mich selbst eingeschlossen, etwas damit anfangen können. :slight_smile:

  • bzgl. Graph im Webfront
    Ich hatte sowas schon gesehen, finde es auf Anhieb auch nicht, nur Medien die Graphen anzeigen, aber halt keine String-Variablen.

*Webfront-Skin`
Der Screenshot ist das Pop-Up-Window vom Log nach dem Beispiel von oben. Habe es jetzt nicht auf mehrere Variablen erweitert, aber ich glaube das glaubst du mir auch so, dass das geht. Wegen der Farbe, falls du das meintest, das ist ein Webfront-Theme… weiß aber nicht mehr welches :wink:

*wegen dem 2-Zeiler und mehr Info
Naja, ich Programmiere jetzt natürlich nicht alles auf Verdacht, aber wenn du gerne wissen möchtest wie es ginge, gern:
Einfach die oben angelegte Variable auf „Textbox“-Profil stellen, das Event abändern auf folgenden Code:

SetValueString("ID_DER_TEXTVARIABLE",GetValueString("ID_DER_TEXTVARIABLE").date("Y-m-d H:i:s")." ".IPS_GetName($_IPS['VARIABLE']) ." ".GetValueFormatted( $_IPS['VARIABLE'])."
");

und du bekommst folgendes Log:

hab etwas mehr ausgeschnitten um zu zeigen das es direkt im Webfront ist.
Datum, Uhrzeit, Name der Variablen und Inhalt

Dann aber das Logging ausstellen, das wäre doppelt gemoppelt. Mir würde noch ein anderer Weg einfallen, aber das ist der schnellste.

Danke für die Antworten!

So wie du es mit dem Textfeld machst, würde das zwar erstmal funktionieren - allerdings würde das Log ja immer länger werden. Die Anzahl der Einträge zu begrenzen wäre nicht mehr so ganz trivial, weil man es mit einem langen String zu tun hat und nicht mit einer Datenstruktur. Klar, geht schon irgendwie, wenn man z.B. nach dem Zeilenumbruch sucht und mit substr hantiert. Aber es ist schon so, dass die simple Lösung da schnell an ihre Grenzen stößt.

Das ist auch einer der Gründe, warum ich mich für den „umständlicheren“ Weg entschieden habe, das Log jeweils aus den letzten n Einträgen zu erzeugen, die ich vom Archive Control bekomme. Es erlaubt mir eine höhere Flexibilität, z.B.

[ul]
[li]die Anzahl der anzuzeigenden Einträge nachträglich zu verändern
[/li][li]nachträglich Variablen zum Log hinzufügen oder herausnehmen
[/li][li]nachträglich das Profil zu bearbeiten und diese Änderungen per Skriptaufruf ins Log zu übernehmen
[/li][/ul]
usw…

Also wie gesagt, ich bin dankbar für konstruktive Hinweise und beispielsweise die Anzeige geloggter Strings im WebFront kannte ich noch nicht und freue mich darüber, dass ich jetzt dazu gelernt habe.

Aber überflüssig finde ich mein Log deshalb lange nicht; es hat meiner Meinung nach ein paar, vor allem ästhetische Vorteile. Für den User ist es zudem sehr simpel zu benutzen, weil man ja einfach ein paar IDs oben in die Liste eintragen muss und das Skript richtet automatisch die notwendigen Textfelder, Events usw. ein - und löscht sie auch wieder, wenn man eine ID aus der Liste entfernt.

Hi,

vielen Dank für dein Skript. Finde es sehr ansprechend und funktioniert Super!

Gruß
Benjamin

Hallo,

zwischenzeitlich funktioniert das Skript - vielen Dank dafür!

Allerdings werden mir die Werte der auszugebenden Float-Variablen nicht farbig angezeigt (bei Boolean und Integer ist die Farbdarstellung korrekt). Wie bekomme ich die Float-Werte farbig?

Vielen Dank für Eure Hilfe und Gruß…

Hat wirklich niemand eine Idee?

Ich kann’s mir nachher mal angucken. Floats mit Associations im Profil, korrekt?

Hallo sokkederheld,

vielen Dank - Floats mit Associations im Profil, damit die Werte farbig dargestellt werden können, korrekt.

Ich hatte Dir eine PN geschrieben, da ich erst später gesehen habe, dass Du bereits hier geantwortet hattest.

Danke für Deine Hilfe und viele Grüße…