273 lines
14 KiB
PHP
273 lines
14 KiB
PHP
<?php
|
|
/**
|
|
* Observium
|
|
*
|
|
* This file is part of Observium.
|
|
*
|
|
* @package observium
|
|
* @subpackage web
|
|
* @copyright (C) Adam Armstrong
|
|
*
|
|
*/
|
|
|
|
// Keep sensors order for base types static
|
|
$sensor_types = [ 'temperature', 'humidity', 'fanspeed', 'airflow', 'current', 'voltage', 'power', 'apower', 'rpower', 'frequency' ];
|
|
$other_types = array_diff(array_keys($config['sensor_types']), $sensor_types);
|
|
$sensor_types = array_merge($sensor_types, $other_types);
|
|
|
|
// Classes without entity association, but with group by measured label
|
|
$measured_label_classes = array_keys($config['sensor_measured']);
|
|
|
|
$measured_entindex = []; // collect measured entities
|
|
$measured_ifindex = []; // collect measured entities (by ifindex)
|
|
$measured_multi = [];
|
|
$sensors_db = [];
|
|
|
|
$sql = "SELECT * FROM `sensors`";
|
|
$sql .= generate_where_clause(["`device_id` = ? ", generate_query_values($sensor_types, 'sensor_class'), "`sensor_deleted` = 0"]);
|
|
$sql .= " ORDER BY CAST(`entPhysicalIndex_measured` AS SIGNED), `measured_entity_label`, CAST(`entPhysicalIndex` AS SIGNED), `sensor_descr`";
|
|
|
|
// Cache all sensors
|
|
foreach (dbFetchRows($sql, [ $device['device_id'] ]) as $entry) {
|
|
if (is_numeric($entry['measured_entity']) && !safe_empty($entry['measured_class'])) {
|
|
// Collect entPhysical entities
|
|
if (!(isset($measured_entindex[$entry['measured_entity']]) || isset($measured_ifindex[$entry['measured_entity']]))) {
|
|
if ($entry['entPhysicalIndex']) {
|
|
$measured_entindex[$entry['measured_entity']] = $entry['entPhysicalIndex'];
|
|
} elseif ($entry['measured_class'] === 'port') {
|
|
// When not correct entPhysicalIndex stored
|
|
$port = get_port_by_id_cache($entry['measured_entity']);
|
|
$measured_ifindex[$entry['measured_entity']] = $port['ifIndex'];
|
|
}
|
|
}
|
|
|
|
// Sensors bounded with measured class, mostly ports
|
|
// array index -> ['measured']['port']['345'][] = sensor array
|
|
switch ($entry['measured_class']) {
|
|
case 'port':
|
|
// Ports can be MultiLane, ie 100Gbit, 40Gbit, detect (currently by descriptions)
|
|
if (preg_match('/(Lane|Channel) (?<lane>\d+)/i', $entry['sensor_descr'], $matches)) {
|
|
$lane = $matches['lane'];
|
|
} else {
|
|
$lane = 0;
|
|
}
|
|
$sensors_db['measured'][$entry['measured_class']][$entry['measured_entity']][$entry['sensor_class']][] = $entry;
|
|
$measured_multi[$entry['measured_class']][$entry['measured_entity']][$lane][$entry['sensor_class']][] = $entry;
|
|
break;
|
|
default:
|
|
$sensors_db['measured'][$entry['measured_class']][$entry['measured_entity']][$entry['sensor_class']][] = $entry;
|
|
}
|
|
|
|
} elseif (in_array($entry['measured_class'], $measured_label_classes, TRUE) && !safe_empty($entry['measured_entity_label'])) {
|
|
// Outlet currently not have real entity associations
|
|
//r($entry);
|
|
$sensors_db['measured'][$entry['measured_class']][$entry['measured_entity_label']][$entry['sensor_class']][] = $entry;
|
|
} else {
|
|
$sensors_db[$entry['sensor_class']][$entry['sensor_id']] = $entry;
|
|
}
|
|
}
|
|
//}
|
|
//r($sensors_db['measured']);
|
|
//r($measured_multi);
|
|
|
|
// Now print founded bundle (measured_class+sensor)
|
|
if (isset($sensors_db['measured'])) {
|
|
$vars['measured_icon'] = FALSE; // Hide measured icons
|
|
|
|
// Fetch entphysical serials and part/vendor names
|
|
$measured_entphysical = [];
|
|
if ($measured_entindex) {
|
|
foreach (dbFetchRows('SELECT * FROM `entPhysical` WHERE `device_id` = ? AND `deleted` IS NULL' . generate_query_values_and($measured_entindex, 'entPhysicalIndex'), [$device['device_id']]) as $entry) {
|
|
foreach ($measured_entindex as $entity_id => $entPhysicalIndex) {
|
|
if ($entPhysicalIndex === $entry['entPhysicalIndex']) {
|
|
if (empty($entry['entPhysicalModelName']) && empty($entry['entPhysicalSerialNum'])) {
|
|
// Containers.. try to get inside
|
|
//r($entry);
|
|
$tmp_entry = dbFetchRow('SELECT * FROM `entPhysical` WHERE `device_id` = ? AND `deleted` IS NULL AND `entPhysicalIndex` = ?', [$device['device_id'], $entry['entPhysicalContainedIn']]);
|
|
if (!empty($tmp_entry['entPhysicalModelName']) || !empty($tmp_entry['entPhysicalSerialNum'])) {
|
|
$entry = $tmp_entry;
|
|
//r($tmp_entry);
|
|
}
|
|
}
|
|
$measured_entphysical[$entity_id] = $entry;
|
|
unset($measured_entindex[$entity_id]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ($measured_ifindex) {
|
|
foreach (dbFetchRows('SELECT * FROM `entPhysical` WHERE `device_id` = ? AND `deleted` IS NULL' . generate_query_values_and($measured_ifindex, 'ifIndex'), [$device['device_id']]) as $entry) {
|
|
foreach ($measured_ifindex as $entity_id => $ifIndex) {
|
|
if ($ifIndex === $entry['ifIndex']) {
|
|
$measured_entphysical[$entity_id] = $entry;
|
|
unset($measured_ifindex[$entity_id]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//r($measured_entphysical);
|
|
|
|
$show_compact = $config['sensors']['web_measured_compact'];
|
|
foreach ($sensors_db['measured'] as $measured_class => $measured_entity) {
|
|
if (isset($config['sensor_measured'][$measured_class])) {
|
|
$measured_title = $config['sensor_measured'][$measured_class]['text'];
|
|
$measured_icon = $config['sensor_measured'][$measured_class]['icon'];
|
|
} else {
|
|
$measured_title = $config['sensor_types'][$measured_class]['text'];
|
|
$measured_icon = $config['sensor_types'][$measured_class]['icon'];
|
|
}
|
|
$measured_title = isset($config['sensor_measured'][$measured_class]) ? $config['sensor_measured'][$measured_class]['text'] : $config['sensor_types'][$measured_class]['text'];
|
|
$box_args = [
|
|
'title' => (empty($measured_title) ? nicecase($measured_class) : $measured_title) . ' sensors',
|
|
'url' => generate_url(['page' => 'device', 'device' => $device['device_id'], 'tab' => $measured_class . 's', 'view' => 'sensors']),
|
|
'icon' => empty($measured_icon) ? $config['icon']['sensor'] : $measured_icon
|
|
];
|
|
$box_args['header-controls'] = [
|
|
'controls' => [
|
|
'compact' => [
|
|
'text' => $show_compact ? 'Full View' : 'Compact View',
|
|
'icon' => $show_compact ? 'glyphicon-th-list' : 'glyphicon-th',
|
|
'config' => 'sensors|web_measured_compact', // check this config
|
|
'value' => $show_compact ? 'no' : 'yes', // toggle
|
|
]
|
|
]
|
|
];
|
|
echo generate_box_open($box_args);
|
|
|
|
echo ' <table class="table table-condensed table-striped">';
|
|
|
|
//r($measured_entity);
|
|
foreach ($measured_entity as $entity_id => $entry) {
|
|
$rename_from = [];
|
|
if (in_array($measured_class, $measured_label_classes, TRUE)) {
|
|
// Outlets not have real entities association
|
|
$entity = [];
|
|
$entity_link = $entity_id; // Just Outlet Label
|
|
$entity_type = $config['sensor_measured'][$measured_class];
|
|
$entity_parts = '';
|
|
$rename_from[] = $entity_id . ' '; // remove measured_entity_label
|
|
} else {
|
|
// Common known entities
|
|
$entity = get_entity_by_id_cache($measured_class, $entity_id);
|
|
//r($entity);
|
|
$entity_link = generate_entity_link($measured_class, $entity);
|
|
$entity_type = entity_type_translate_array($measured_class);
|
|
$entity_parts = '';
|
|
if ($measured_entphysical[$entity_id]) {
|
|
// Entity Vendor/PartNum/Serial
|
|
if ($measured_entphysical[$entity_id]['entPhysicalMfgName']) {
|
|
$entity_parts .= ' <span class="label label-info">' . $measured_entphysical[$entity_id]['entPhysicalMfgName'] . '</span>';
|
|
}
|
|
if ($measured_entphysical[$entity_id]['entPhysicalModelName']) {
|
|
$entity_parts .= ' <span class="label label-warning">' . $measured_entphysical[$entity_id]['entPhysicalModelName'] . '</span>';
|
|
}
|
|
if ($measured_entphysical[$entity_id]['entPhysicalSerialNum']) {
|
|
$entity_parts .= ' <span class="label label-primary">SN: ' . $measured_entphysical[$entity_id]['entPhysicalSerialNum'] . '</span>';
|
|
}
|
|
}
|
|
|
|
// Remove port name from sensor description
|
|
if ($measured_class === 'port') {
|
|
if (is_numeric($entity['port_label'])) {
|
|
$rename_from[] = $entity['port_label'] . ' ';
|
|
} else {
|
|
$rename_from[] = $entity['port_label'];
|
|
$rename_from[] = $entity['ifDescr'];
|
|
$rename_from[] = $entity['port_label_short'];
|
|
}
|
|
if (strlen($entity['port_label_base']) > 4) {
|
|
$rename_from[] = $entity['port_label_base'];
|
|
}
|
|
$rename_from = array_unique($rename_from);
|
|
} else {
|
|
entity_rewrite($measured_class, $entity);
|
|
}
|
|
$entity['rename_from'] = $rename_from;
|
|
}
|
|
|
|
echo(' <tr>
|
|
<td colspan="6" class="entity">' . get_icon($entity_type['icon']) . ' ' . $entity_link . $entity_parts . '</td></tr>');
|
|
|
|
if ($show_compact && (!in_array($measured_class, $measured_label_classes, TRUE) ||
|
|
$config['sensor_measured'][$measured_class]['compact'])) {
|
|
// In compact view need multi-lane split
|
|
$lanes_count = safe_count($measured_multi[$measured_class][$entity_id]);
|
|
if ($lanes_count > 1) {
|
|
if (isset($measured_multi[$measured_class][$entity_id][0]) && $lanes_count === 5) {
|
|
// Multilane with separated voltage or others
|
|
for ($i = 1; $i <= 4; $i++) {
|
|
$measured_multi[$measured_class][$entity_id][$i] = array_merge($measured_multi[$measured_class][$entity_id][$i],
|
|
$measured_multi[$measured_class][$entity_id][0]);
|
|
}
|
|
unset($measured_multi[$measured_class][$entity_id][0]);
|
|
}
|
|
foreach ($measured_multi[$measured_class][$entity_id] as $lane => $lane_entry) {
|
|
echo '<tr><td style="width: 10px;" class="vertical-align"><span class="label">L' . $lane . '</span></td>' .
|
|
get_compact_sensors_line($measured_class, $lane_entry, $vars) . '</tr>';
|
|
}
|
|
} else {
|
|
echo '<tr><td style="width: 10px;"></td>' . get_compact_sensors_line($measured_class, $entry, $vars) . '</tr>';
|
|
}
|
|
} else {
|
|
// order dom sensors always by temperature, voltage, current, dbm, power
|
|
$order = [];
|
|
if (safe_count($entry) > 0) {
|
|
$classes = array_keys($entry);
|
|
$order = array_intersect(['temperature', 'voltage', 'current', 'dbm', 'power'], $classes);
|
|
$order = array_merge($order, array_diff($classes, $order));
|
|
}
|
|
|
|
foreach ($order as $class) {
|
|
foreach ($entry[$class] as $sensor) {
|
|
$sensor['sensor_descr_short'] = trim(str_ireplace($rename_from, '', $sensor['sensor_descr']), ":- \t\n\r\0\x0B");
|
|
if (empty($sensor['sensor_descr_short'])) {
|
|
// Some time sensor descriptions equals to entity name
|
|
$sensor['sensor_descr'] = nicecase($sensor['sensor_class']);
|
|
} elseif (str_starts_with($sensor['sensor_descr_short'], '(')) {
|
|
$sensor['sensor_descr'] = nicecase($sensor['sensor_class']) . ' ' . $sensor['sensor_descr_short'];
|
|
} else {
|
|
$sensor['sensor_descr'] = $sensor['sensor_descr_short'];
|
|
}
|
|
|
|
print_sensor_row($sensor, $vars);
|
|
}
|
|
}
|
|
}
|
|
|
|
//if ($show_compact) { echo '<tr>' . $line . '</tr>'; }
|
|
}
|
|
|
|
?>
|
|
</table>
|
|
<?php
|
|
echo generate_box_close();
|
|
}
|
|
// End for print bounds, unset this array
|
|
unset($sensors_db['measured']);
|
|
}
|
|
|
|
foreach ($sensor_types as $sensor_type) {
|
|
if (safe_empty($sensors_db[$sensor_type])) {
|
|
continue;
|
|
}
|
|
|
|
$box_args = [
|
|
'title' => nicecase($sensor_type),
|
|
'url' => generate_url(['page' => 'device', 'device' => $device['device_id'], 'tab' => 'health', 'metric' => $sensor_type]),
|
|
'icon' => $config['sensor_types'][$sensor_type]['icon'],
|
|
];
|
|
echo generate_box_open($box_args);
|
|
|
|
echo('<table class="table table-condensed table-striped">');
|
|
foreach ($sensors_db[$sensor_type] as $sensor) {
|
|
print_sensor_row($sensor, $vars);
|
|
}
|
|
|
|
echo("</table>");
|
|
echo generate_box_close();
|
|
}
|
|
|
|
// EOF
|