Ich hab die Leerzeichen rausgeholt.
Es gibt ein Problem bei dem Node1. Ich wollte Zeit sparen und hab ihn übersprungen.
Dan fehlen natürlich die Daten für das json Array.
Ersetze doch bitte das Script generate-data mit dem folgenden:
<?
// Name für Log-Messages
$logname = "graphml";
// Anzahl der Z-Wave "pings"
$num_route_tests = 5;
// Id der Kategorie für die Visualisierung
//$cat_id = 17069 /*[Funktionen\Z-Wave\viz_mesh]*/;
$cat_id = IPS_GetParent($_IPS['SELF']);
// Ermitteln des Konfigurators
// Bei Angabe von 0 werden die ids automatisch ermittelt.
$zw_konf = 0;
$zw_gw = 0;
$ach = 0; // ID des Archiveshanlders
// Pfad für xml Datei
$xml_path = IPS_GetKernelDir().'/webfront/user/viz_mesh/';
// Grösse der Graphdarstellung
$size_x = 512;
$size_y = 512;
// Auflistung aller bekannten Z-Wave Klassen
$class_name=Array(0=>'COMMAND_CLASS_NO_OPERATION',
32=>'COMMAND_CLASS_BASIC',
33=>'COMMAND_CLASS_CONTROLLER_REPLICATION',
34=>'COMMAND_CLASS_APPLICATION_STATUS',
35=>'COMMAND_CLASS_ZIP_SERVICES',
36=>'COMMAND_CLASS_ZIP_SERVER',
37=>'COMMAND_CLASS_SWITCH_BINARY',
38=>'COMMAND_CLASS_SWITCH_MULTILEVEL',
38=>'COMMAND_CLASS_SWITCH_MULTILEVEL_V2',
39=>'COMMAND_CLASS_SWITCH_ALL',
40=>'COMMAND_CLASS_SWITCH_TOGGLE_BINARY',
41=>'COMMAND_CLASS_SWITCH_TOGGLE_MULTILEVEL',
42=>'COMMAND_CLASS_CHIMNEY_FAN',
43=>'COMMAND_CLASS_SCENE_ACTIVATION',
44=>'COMMAND_CLASS_SCENE_ACTUATOR_CONF',
45=>'COMMAND_CLASS_SCENE_CONTROLLER_CONF',
46=>'COMMAND_CLASS_ZIP_CLIENT',
47=>'COMMAND_CLASS_ZIP_ADV_SERVICES',
48=>'COMMAND_CLASS_SENSOR_BINARY',
49=>'COMMAND_CLASS_SENSOR_MULTILEVEL',
49=>'COMMAND_CLASS_SENSOR_MULTILEVEL_V2',
50=>'COMMAND_CLASS_METER',
51=>'COMMAND_CLASS_ZIP_ADV_SERVER',
52=>'COMMAND_CLASS_ZIP_ADV_CLIENT',
53=>'COMMAND_CLASS_METER_PULSE',
53=>'COMMAND_CLASS_METER_TBL_CONFIG',
53=>'COMMAND_CLASS_METER_TBL_MONITOR',
53=>'COMMAND_CLASS_METER_TBL_PUSH',
56=>'COMMAND_CLASS_THERMOSTAT_HEATING',
64=>'COMMAND_CLASS_THERMOSTAT_MODE',
66=>'COMMAND_CLASS_THERMOSTAT_OPERATING_STATE',
67=>'COMMAND_CLASS_THERMOSTAT_SETPOINT',
68=>'COMMAND_CLASS_THERMOSTAT_FAN_MODE',
69=>'COMMAND_CLASS_THERMOSTAT_FAN_STATE',
70=>'COMMAND_CLASS_CLIMATE_CONTROL_SCHEDULE',
71=>'COMMAND_CLASS_THERMOSTAT_SETBACK',
76=>'COMMAND_CLASS_DOOR_LOCK_LOGGING',
78=>'COMMAND_CLASS_SCHEDULE_ENTRY_LOCK',
80=>'COMMAND_CLASS_BASIC_WINDOW_COVERING',
81=>'COMMAND_CLASS_MTP_WINDOW_COVERING',
96=>'COMMAND_CLASS_MULTI_CHANNEL_V2',
96=>'COMMAND_CLASS_MULTI_INSTANCE',
98=>'COMMAND_CLASS_DOOR_LOCK',
99=>'COMMAND_CLASS_USER_CODE',
112=>'COMMAND_CLASS_CONFIGURATION',
112=>'COMMAND_CLASS_CONFIGURATION_V2',
113=>'COMMAND_CLASS_ALARM',
114=>'COMMAND_CLASS_MANUFACTURER_SPECIFIC',
115=>'COMMAND_CLASS_POWERLEVEL',
117=>'COMMAND_CLASS_PROTECTION',
117=>'COMMAND_CLASS_PROTECTION_V2',
118=>'COMMAND_CLASS_LOCK',
119=>'COMMAND_CLASS_NODE_NAMING',
122=>'COMMAND_CLASS_FIRMWARE_UPDATE_MD',
123=>'COMMAND_CLASS_GROUPING_NAME',
124=>'COMMAND_CLASS_REMOTE_ASSOCIATION_ACTIVATE',
125=>'COMMAND_CLASS_REMOTE_ASSOCIATION',
128=>'COMMAND_CLASS_BATTERY',
129=>'COMMAND_CLASS_CLOCK',
130=>'COMMAND_CLASS_HAIL',
132=>'COMMAND_CLASS_WAKE_UP',
132=>'COMMAND_CLASS_WAKE_UP_V2',
133=>'COMMAND_CLASS_ASSOCIATION',
133=>'COMMAND_CLASS_ASSOCIATION_V2',
134=>'COMMAND_CLASS_VERSION',
135=>'COMMAND_CLASS_INDICATOR',
136=>'COMMAND_CLASS_PROPRIETARY',
137=>'COMMAND_CLASS_LANGUAGE',
138=>'COMMAND_CLASS_TIME',
139=>'COMMAND_CLASS_TIME_PARAMETERS',
140=>'COMMAND_CLASS_GEOGRAPHIC_LOCATION',
141=>'COMMAND_CLASS_COMPOSITE',
142=>'COMMAND_CLASS_MULTI_CHANNEL_ASSOCIATION_V2',
142=>'COMMAND_CLASS_MULTI_INSTANCE_ASSOCIATION',
143=>'COMMAND_CLASS_MULTI_CMD',
144=>'COMMAND_CLASS_ENERGY_PRODUCTION',
145=>'COMMAND_CLASS_MANUFACTURER_PROPRIETARY',
146=>'COMMAND_CLASS_SCREEN_MD',
146=>'COMMAND_CLASS_SCREEN_MD_V2',
147=>'COMMAND_CLASS_SCREEN_ATTRIBUTES',
147=>'COMMAND_CLASS_SCREEN_ATTRIBUTES_V2',
148=>'COMMAND_CLASS_SIMPLE_AV_CONTROL',
149=>'COMMAND_CLASS_AV_CONTENT_DIRECTORY_MD',
150=>'COMMAND_CLASS_AV_RENDERER_STATUS',
151=>'COMMAND_CLASS_AV_CONTENT_SEARCH_MD',
152=>'COMMAND_CLASS_SECURITY',
153=>'COMMAND_CLASS_AV_TAGGING_MD',
154=>'COMMAND_CLASS_IP_CONFIGURATION',
155=>'COMMAND_CLASS_ASSOCIATION_COMMAND_CONFIGURATION',
156=>'COMMAND_CLASS_SENSOR_ALARM',
157=>'COMMAND_CLASS_SILENCE_ALARM',
158=>'COMMAND_CLASS_SENSOR_CONFIGURATION',
239=>'COMMAND_CLASS_MARK',
240=>'COMMAND_CLASS_NON_INTEROPERABLE');
foreach (IPS_GetInstanceList() as $id)
{
$inst = IPS_GetInstance($id);
if (($zw_konf == 0) && ($inst['ModuleInfo']['ModuleID'] == '{2D7CA355-2C51-4430-8F67-4E397EAAEA19}'))
$zw_konf = $id;
if (($zw_gw == 0) && ($inst['ModuleInfo']['ModuleID'] == '{4EF72D56-BF9F-4347-8F0A-2035D241116F}'))
$zw_gw = $id;
if (($ach == 0) && ($inst['ModuleInfo']['ModuleID'] == '{43192F0B-135B-4CE7-A0A7-1475603F3060}'))
$ach = $id;
}
if (($zw_konf == 0) || ($zw_gw==0))
die ('Keine Z-Wave Konfigurator/Gateway Instanz gefunden.');
if (!($devices = ZW_GetKnownDevices($zw_konf)))
die ('Keine Z-Wave Geräte gefunden.');
// Ermittlung der Bedienelemente
$scan_id = GetObjectID('./Bedienung/Scan');
$opt_id = GetObjectID('./Bedienung/mit Optimierung');
$devout_id = GetObjectID('./Bedienung/Gerät');
// Ermittlung einiger benötiger VariablenIDs
$kur_id = GetObjectID('./Kurve/Trend');
$script_id = GetObjectID('./Kurve/Trend/Update');
$iF_id = GetObjectID('./Grafik/iFrame');
//Wenn das Script nicht vom Timer aufgerufen wird starten wir den Timer
if ($_IPS['SENDER'] != 'TimerEvent')
{
// Überprüfen der Kurvenvariable
if (($kur_id > 0) && ($script_id > 0))
SetValueString($kur_id, '<iframe src="./user/Highcharts/IPS_Template.php?ScriptId='.$script_id.'&mini=true&height=270" width="100%" height=270 frameborder="0" scrolling="no"></iframe>');
if ($iF_id > 0)
SetValueString($iF_id, '<iframe src="./user/viz_mesh/viz_mesh.html" width="100%" height=560 frameborder="0" scrolling="no"></iframe>');
IPS_SetScriptTimer($_IPS['SELF'], 1);
exit(0);
}
if (($_IPS['SENDER'] == 'TimerEvent') && !GetValueBoolean($scan_id))
{
SetValueBoolean($scan_id, true);
exit(0);
}
// Abfragen der einzelnen ZW_nodes
// Dies wird in einer Timerschleife erledigt damit der Funkbus nicht überlastet wird.
$finished = true;
// Speicher für bereits abgefragte Geräte einrichten
$historyID = CreateVariableByName($_IPS['SELF'], "History", 3, "");
$history = explode(',', GetValue($historyID));
IPS_SetScriptTimer($_IPS['SELF'], 0);
foreach ($devices as $dev)
{
$id = $dev['InstanceID'];
// Gerät bearbeiten wenn wir es noch nicht bearbeitet haben.
if (!in_array($id, $history))
{
$finished = false;
//echo "Abfragen von ".IPS_GetName($id).".
";
$name = IPS_GetName(IPS_GetParent($id))."/".IPS_GetName($id);
// Das Routing des Gerätes testen
$good = 0;
$times = Array();
IPS_LogMessage($logname, $name." wird getestet.");
SetValueString($devout_id, $name);
if (GetValueBoolean($opt_id))
{
//IPS_LogMessage($logname, "Routing wird optimiert.");
SetValueString($devout_id, $name . " (opt.)");
ZW_RoutingOptimizeNode($zw_gw, $dev['NodeID']);
}
for ($i=1;$i<=$num_route_tests;$i++)
{
//IPS_LogMessage($logname, IPS_GetName($id)." wird getestet. (".$i."/".$num_route_tests.")");
// IPS_LogMessage($logname, "-------------");
SetValueString($devout_id, $name . " (".$i."/".$num_route_tests.")");
$start = microtime(true);
//IPS_LogMessage($logname, "Start: ".$start);
if (ZW_RoutingTestNode($zw_gw, $dev['NodeID']))
{
$time = round((microtime(true) - $start)*1000);
$good++;
$times[] = $time;
IPS_LogMessage($logname, "Ping erfolgreich (".$good."/".$num_route_tests." in ".$time."ms)");
}
IPS_Sleep(200);
}
// Errechne die durchschnittliche pingzeit
$avg = 0;
foreach($times as $t)
{
$avg += $t;
}
if ($good > 0)
$avg = $avg / $good;
else
{
$avg = 0;
IPS_LogMessage($logname, $name." ist nicht erreichbar.");
}
$NumPingID = CreateVariableByName($id, "NumPing", 1, "");
IPS_SetHidden($NumPingID, true);
AC_SetLoggingStatus($ach, $NumPingID, true);
SetValue($NumPingID, $good);
$timeID = CreateVariableByName($id, "PingTime", 1, "");
IPS_SetHidden($timeID, true);
AC_SetLoggingStatus($ach, $timeID, true);
SetValue($timeID, $avg);
//Gerät abfragen
IPS_LogMessage($logname, "Abfrage von ".$name);
SetValueString($devout_id, $name . " (config)");
if (@ZW_RequestInfo($id))
IPS_LogMessage($logname, "Abfrage erfolgreich.");
else
IPS_LogMessage($logname, "Abfrage fehlerhaft.");
$history[] = $id;
SetValue($historyID, implode(',', $history));
break;
}
}
if (!$finished)
{
IPS_SetScriptTimer($_IPS['SELF'], 5);
exit(0);
}
else
{
IPS_LogMessage($logname, "Abfragen der Geräte beendet.");
//IPS_SetScriptTimer($_IPS['SELF'], 0);
// History löschen, damit beim nächsten mal wieder alle Geräte abgefragt werden.
SetValue($historyID, "");
SetValueString($devout_id, "");
SetValueBoolean($scan_id, false);
}
foreach ($devices as $dev)
{
$id = $dev['InstanceID'];
$dev_inst = IPS_GetInstance($id);
$dev_obj = IPS_GetObject($id);
$dev_classes = ZW_GetNodeClasses($id);
if (!($grp_count = @ZW_AssociationGetGroupCount($id)))
$grp_count = 0;
$dev_grp = Array();
for ($i=1; $i <= $grp_count;$i++)
$dev_grp = array_merge($dev_grp, ZW_AssociationGetGroupNodes($id, $i));
//$dev_grp[$i] = ZW_AssociationGetGroupNodes($id, $i);
$dev_routing = ZW_RoutingGetNodes($zw_gw, $dev['NodeID']);
// Array mit den gewünschten Informationen zusammenstellen
// Name mit der übergelagerten Instanz auffüllen
$name = utf8_encode(str_replace(Array("[","]","{","}"), Array("(",")","(",")"), IPS_GetName(IPS_GetParent($id))."/".utf8_encode(IPS_GetName($id))));
// Übersetzen der Klassen in ein String Array
$dev_classes_name = Array();
foreach ($dev_classes as $class)
$dev_classes_name[$class] = $class_name[$class];
// Lesen der Daten des Routingtests
$NumPingID = @IPS_GetVariableIDByName("NumPing", $id);
$avgID = @IPS_GetVariableIDByName("PingTime", $id);
$NumPing = @GetValue($NumPingID);
$avg = @GetValue($avgID);
$nodes[] = Array('NodeID'=>$dev['NodeID'], 'Name'=>$name, 'InstanceID'=>$id, 'NumPings'=>$NumPing, 'PingTime'=>$avg, 'grp_count'=>$grp_count, 'GrpAssoc'=>$dev_grp, 'routing'=>$dev_routing, 'Classes'=>$dev_classes_name);
// echo "------- Gerät ENDE------
";
}
//echo "Node:
";
//print_r($nodes);
//IPS_LogMessage($logname, "Nodes:
". print_r($node, true));
//Generieren der xml Datei
$data ='<?xml version="1.0" encoding="UTF-8"?>
<!-- A List of nodes for homeautomation -->
<graphml xmlns="http://graphml.graphdrawing.org/xmlns">
<graph id="Routing" edgedefault="directed">
<!-- data schema -->
<key id="NodeID" for="node" attr.name="NodeID" attr.type="int"/>
<key id="Name" for="node" attr.name="Name" attr.type="string"/>
<key id="InstanceID" for="node" attr.name="InstanceID" attr.type="int"/>
<key id="Classes" for="node" attr.name="Classes" attr.type="string"/>
<key id="NumPings" for="node" attr.name="NumPings" attr.type="int"/>
<key id="PingTime" for="node" attr.name="PingTime" attr.type="int"/>
<!-- nodes -->
';
$ids = Array();
$c_id = 0;
$json = '{"nodes":[';
foreach ($nodes as $node)
{
/*
$data .= '<node id="'.$node['NodeID'].'">
<data key="NodeID">'.$node['NodeID'].'</data>
<data key="Name">'.$node['Name'].'</data>
<data key="InstanceID">'.$node['InstanceID'].'</data>
<data key="NumPings">'.$node['NumPings'].'</data>
<data key="PingTime">'.$node['PingTime'].'</data>
<data key="Classes">
'.implode("
", $node['Classes']).'
</data>
</node>
';
*/
//PingTime == 0 abfangen
if ($node['PingTime'] == 0)
$node['PingTime'] = 9999;
$data .= '<node id="'.$node['NodeID'].'" Name="'.$node['Name'].'" InstanceID="'.$node['InstanceID'].'" NumPings="'.$node['NumPings'].'" PingTime="'.$node['PingTime'].'">
<data key="Classes">
'.implode("
", $node['Classes']).'
</data>
</node>
';
$ids[$node['NodeID']] = $c_id;
$json .= '{"id":'.$node['NodeID'].',"nodeName":"'.utf8_decode($node['Name']).'","InstanceID":'.$node['InstanceID'].',"NumPings":'.$node['NumPings'].',"PingTime":'.$node['PingTime'].'},';
$c_id++;
}
$json .= '],';
$data .= '
<!-- edges -->
';
$json .= '"links":[';
foreach ($nodes as $node)
{
foreach ($node['routing'] as $route)
{
$data .='<edge source="'.$node['NodeID'].'" target="'.$route.'"></edge>
';
$json .= '{"source":'.$ids[$node['NodeID']].',"target":'.$ids[$route].',"value":1},';
}
}
$json .= '],';
// Konfigurationswerte anhängen
$json .= '"config":[{"catid":'.$cat_id.',"maxping":'.$num_route_tests.',"size_x":'.$size_x.',"size_y":'.$size_y.'}]}';
$data .= '</graph>
</graphml>
';
//print $data;
//IPS_LogMessage($logname, $json);
$json = str_replace(',]', ']', $json);
$json = str_replace(',}', '}', $json);
// Datei schreiben
$file = fopen($xml_path."graph.xml", "w");
fwrite($file, utf8_encode($data));
fclose($file);
$file = fopen($xml_path."graph.json", "w");
fwrite($file, utf8_encode($json));
fclose($file);
IPS_LogMessage($logname, "xml Datei geschrieben.");
// Die Grafik antriggern um sie neu darzustellen
if ($iF_id > 0)
SetValueString($iF_id,GetValueString($iF_id));
if($kur_id > 0)
SetValueString($kur_id,GetValueString($kur_id));
function CreateVariableByName($id, $name, $type, $profile = "")
{
$vid = @IPS_GetVariableIDByName($name, $id);
if($vid === false)
{
$vid = IPS_CreateVariable($type);
IPS_SetParent($vid, $id);
IPS_SetName($vid, $name);
IPS_SetInfo($vid, "this variable was created by script #".$_IPS['SELF']);
if($profile !== "")
{
IPS_SetVariableCustomProfile($vid, $profile);
}
}
return $vid;
}
// GetObject ID ermittelt die ID eines Objects anhand eineer Pfadangabe
// diese kann auch relativ erfolgen. Z.B. mit "./" oder "../"
function GetObjectID($strObject, $parent = 0){
$child = 0;
// "/" sowie "\" werden als Trennzeichen akzeptiert
$Objects = explode("/", str_replace("\\", "/", $strObject));
//IPS_LogMessage("getObjectID", "Objects: " . print_r($Objects));
foreach ($Objects as $Object){
if($Object == ".")
{
if ($parent == 0)
$child = $parent = IPS_GetParent($_IPS['SELF']);
else
$child = $parent;
}
elseif ($Object == "..")
{
if (($child == 0) && ($parent == 0))
$child = $parent = IPS_GetParent(IPS_GetParent($_IPS['SELF']));
elseif ($child == 0)
$child = $parent = IPS_GetParent($parent);
else
$child = $parent = IPS_GetParent($child);
}
else
{
try { $child = IPS_GetObjectIDByName($Object, $parent); }
catch(Exception $e){ return 0; }
if ($child > 0){ $parent = $child; }
else { return 0; }
}
}
return $child;
}
?>
Dann noch mal einen Scan machen.
Die Kreise sind bei so vielen Verbindungen zu gross. Das werd ich noch anpassen.
P.S.: Nach dem 0:3 war dann doch noch Zeit.
cu…