function discover_sensor(&$valid, $class, $device, $oid, $index, $type, $sensor_descr, $scale = 1, $current = NULL, $options = array(), $poller_type = 'snmp') { global $config; // Init main $param_main = array('oid' => 'sensor_oid', 'sensor_descr' => 'sensor_descr', 'scale' => 'sensor_multiplier'); // Init numeric values if (!is_numeric($scale) || $scale == 0) { $scale = 1; } $param_limits = array('limit_high' => 'sensor_limit', 'limit_high_warn' => 'sensor_limit_warn', 'limit_low_warn' => 'sensor_limit_low_warn', 'limit_low' => 'sensor_limit_low'); foreach ($param_limits as $key => $column) { ${$key} = is_numeric($options[$key]) ? $options[$key] : NULL; } // Init optional $param_opt = array('entPhysicalIndex', 'entPhysicalClass', 'entPhysicalIndex_measured', 'measured_class', 'measured_entity'); foreach ($param_opt as $key) { ${$key} = $options[$key] ? $options[$key] : NULL; } print_debug("Discover sensor: {$class}, " . $device['hostname'] . ", {$oid}, {$index}, {$type}, {$sensor_descr}, {$scale}, {$limit_low}, {$limit_low_warn}, {$limit_high_warn}, {$limit_high}, {$current}, {$poller_type}, {$entPhysicalIndex}, {$entPhysicalClass}"); // Check sensor ignore filters foreach ($config['ignore_sensor'] as $bi) { if (strcasecmp($bi, $sensor_descr) == 0) { print_debug("Skipped by equals: {$bi}, {$sensor_descr} "); return FALSE; } } foreach ($config['ignore_sensor_string'] as $bi) { if (stripos($sensor_descr, $bi) !== FALSE) { print_debug("Skipped by strpos: {$bi}, {$sensor_descr} "); return FALSE; } } foreach ($config['ignore_sensor_regexp'] as $bi) { if (preg_match($bi, $sensor_descr) > 0) { print_debug("Skipped by regexp: {$bi}, {$sensor_descr} "); return FALSE; } } if (!is_null($limit_low_warn) && !is_null($limit_high_warn) && $limit_low_warn > $limit_high_warn) { // Fix high/low thresholds (i.e. on negative numbers) list($limit_high_warn, $limit_low_warn) = array($limit_low_warn, $limit_high_warn); } if (dbFetchCell('SELECT COUNT(`sensor_id`) FROM `sensors` WHERE `poller_type`= ? AND `sensor_class` = ? AND `device_id` = ? AND `sensor_type` = ? AND `sensor_index` = ?', array($poller_type, $class, $device['device_id'], $type, $index)) == '0') { if (!isset($config['sensor_states'][$type])) { if (!$limit_high) { $limit_high = sensor_limit_high($class, $current); } if (!$limit_low) { $limit_low = sensor_limit_low($class, $current); } if (!is_null($limit_low) && !is_null($limit_high) && $limit_low > $limit_high) { // Fix high/low thresholds (i.e. on negative numbers) list($limit_high, $limit_low) = array($limit_low, $limit_high); } } else { // For state sensors limits always is NULL $limit_high = NULL; $limit_low = NULL; $limit_high_warn = NULL; $limit_low_warn = NULL; } $sensor_insert = array('poller_type' => $poller_type, 'sensor_class' => $class, 'device_id' => $device['device_id'], 'sensor_index' => $index, 'sensor_type' => $type); foreach ($param_main as $key => $column) { $sensor_insert[$column] = ${$key}; } foreach ($param_limits as $key => $column) { // Convert strings/numbers to (float) or to array('NULL') ${$key} = ${$key} === NULL ? array('NULL') : (double) ${$key}; $sensor_insert[$column] = ${$key}; } foreach ($param_opt as $key) { if (is_null(${$key})) { ${$key} = array('NULL'); } $sensor_insert[$key] = ${$key}; } $sensor_id = dbInsert($sensor_insert, 'sensors'); $state_insert = array('sensor_id' => $sensor_id, 'sensor_value' => $current, 'sensor_polled' => 'NOW()'); dbInsert($state_insert, 'sensors-state'); print_debug("( {$sensor_id} inserted )"); echo "+"; log_event("Sensor added: {$class} {$type} {$index} {$sensor_descr}", $device, 'sensor', $sensor_id); } else { $sensor_entry = dbFetchRow("SELECT * FROM `sensors` WHERE `sensor_class` = ? AND `device_id` = ? AND `sensor_type` = ? AND `sensor_index` = ?", array($class, $device['device_id'], $type, $index)); // Limits if (!$sensor_entry['sensor_custom_limit']) { if (!isset($config['sensor_states'][$type])) { if (!is_numeric($limit_high) && !is_numeric($limit_low)) { if (!$sensor_entry['sensor_limit']) { // Calculate a reasonable limit $limit_high = sensor_limit_high($class, $current); } else { // Use existing limit. (this is wrong! --mike) $limit_high = $sensor_entry['sensor_limit']; } if (!$sensor_entry['sensor_limit_low']) { // Calculate a reasonable limit $limit_low = sensor_limit_low($class, $current); } else { // Use existing limit. (this is wrong! --mike) $limit_low = $sensor_entry['sensor_limit_low']; } } // Fix high/low thresholds (i.e. on negative numbers) if (!is_null($limit_low) && !is_null($limit_high) && $limit_low > $limit_high) { list($limit_high, $limit_low) = array($limit_low, $limit_high); } } else { // For state sensors limits always is NULL $limit_high = NULL; $limit_low = NULL; $limit_high_warn = NULL; $limit_low_warn = NULL; } // Update limits $update = array(); $msg_debug = 'Current sensor value: "' . $current . '", scale: "' . $scale . '"' . PHP_EOL; foreach ($param_limits as $v => $k) { $msg_debug .= ' ' . $v . ': "' . $sensor_entry[$k] . '" -> "' . ${$v} . '"' . PHP_EOL; //convert strings/numbers to identical type (float) or to array('NULL') for correct comparison ${$v} = ${$v} === NULL ? array('NULL') : (double) ${$v}; $sensor_entry[$k] = $sensor_entry[$k] === NULL ? array('NULL') : (double) $sensor_entry[$k]; if (float_cmp(${$v}, $sensor_entry[$k]) !== 0) { $update[$k] = ${$v}; } } if (count($update)) { echo "L"; print_debug($msg_debug); $msg = 'Sensor updated (limits): ' . $class . ' ' . $type . ' ' . $index . ' ' . $sensor_descr . ' '; foreach (array('L' => 'sensor_limit_low', 'Lw' => 'sensor_limit_low_warn', 'Hw' => 'sensor_limit_warn', 'H' => 'sensor_limit') as $v => $k) { if (isset($update[$k])) { $msg .= is_array($update[$k]) ? "[{$v}: " . $update[$k][0] . "]" : "[{$v}: " . $update[$k] . "]"; } } log_event($msg, $device, 'sensor', $sensor_entry['sensor_id']); $updated = dbUpdate($update, 'sensors', '`sensor_id` = ?', array($sensor_entry['sensor_id'])); } } $update = array(); foreach ($param_main as $key => $column) { if (float_cmp(${$key}, $sensor_entry[$column]) !== 0) { $update[$column] = ${$key}; } } foreach ($param_opt as $key) { if (${$key} != $sensor_entry[$key]) { $update[$key] = ${$key}; } } if (count($update)) { $updated = dbUpdate($update, 'sensors', '`sensor_id` = ?', array($sensor_entry['sensor_id'])); echo "U"; log_event("Sensor updated: {$class} {$type} {$index} {$sensor_descr}", $device, 'sensor', $sensor_entry['sensor_id']); } else { echo "."; } } $valid[$class][$type][$index] = 1; }
/** * Discover a new sensor on a device * * This function adds a status sensor to a device, if it does not already exist. * Data on the sensor is updated if it has changed, and an event is logged with regards to the changes. * * Status sensors are handed off to discover_status(). * Current sensor values are rectified in case they are broken (added spaces, etc). * * @param array &$valid Array of currently valid sensors for poller type (used to delete later) * @param string $class Class of sensor (voltage, temperature, etc.) * @param array $device Device array sensor is being discovered on * @param string $oid SNMP OID of sensor * @param string $index SNMP index of sensor * @param string $type Type of sensor * @param string $sensor_descr Description of sensor * @param int $scale Scale of sensor (0.1 for 1:10 scale, 10 for 10:1 scale, etc) * @param string $value Current sensor value * @param array $options Options (sensor_unit, limit_auto, limit*) * @param string $poller_type Type of poller being used (SNMP, Agent, etc) - Used to check valid sensors per poller type * @return bool */ function discover_sensor(&$valid, $class, $device, $oid, $index, $type, $sensor_descr, $scale = 1, $value = NULL, $options = array(), $poller_type = 'snmp') { global $config; // If this is actually a status indicator, pass it off to discover_status() then return. if ($class == 'state' || $class == 'status') { print_debug("Redirecting call to discover_status()."); return discover_status($device, $oid, $index, $type, $sensor_descr, $value, $options, $poller_type); } // Init main $param_main = array('oid' => 'sensor_oid', 'sensor_descr' => 'sensor_descr', 'scale' => 'sensor_multiplier'); // Init numeric values if (!is_numeric($scale) || $scale == 0) { $scale = 1; } // Skip discovery sensor if value not numeric or null (default) if (strlen($value)) { // Some retarded devices report data with spaces and commas // STRING: " 20,4" $value = snmp_fix_numeric($value); } if (is_numeric($value)) { $value *= $scale; // Scale before unit conversion $value = value_to_si($value, $options['sensor_unit'], $class); // Convert if not SI unit } else { print_debug("Sensor skipped by not numeric value: '{$value}', '{$sensor_descr}'"); if (strlen($value)) { print_debug("Perhaps this is named sensor, use discover_status() instead."); } return FALSE; } $param_limits = array('limit_high' => 'sensor_limit', 'limit_high_warn' => 'sensor_limit_warn', 'limit_low' => 'sensor_limit_low', 'limit_low_warn' => 'sensor_limit_low_warn'); foreach ($param_limits as $key => $column) { // Set limits vars and unit convert if required ${$key} = is_numeric($options[$key]) ? value_to_si($options[$key], $options['sensor_unit'], $class) : NULL; } // Auto calculate high/low limits if not passed $limit_auto = !isset($options['limit_auto']) || (bool) $options['limit_auto']; // Init optional $param_opt = array('entPhysicalIndex', 'entPhysicalClass', 'entPhysicalIndex_measured', 'measured_class', 'measured_entity', 'sensor_unit'); foreach ($param_opt as $key) { ${$key} = $options[$key] ? $options[$key] : NULL; } print_debug("Discover sensor: {$class}, " . $device['hostname'] . ", {$oid}, {$index}, {$type}, {$sensor_descr}, SCALE: {$scale}, LIMITS: ({$limit_low}, {$limit_low_warn}, {$limit_high_warn}, {$limit_high}), CURRENT: {$value}, {$poller_type}, {$entPhysicalIndex}, {$entPhysicalClass}"); // Check sensor ignore filters foreach ($config['ignore_sensor'] as $bi) { if (strcasecmp($bi, $sensor_descr) == 0) { print_debug("Skipped by equals: {$bi}, {$sensor_descr} "); return FALSE; } } foreach ($config['ignore_sensor_string'] as $bi) { if (stripos($sensor_descr, $bi) !== FALSE) { print_debug("Skipped by strpos: {$bi}, {$sensor_descr} "); return FALSE; } } foreach ($config['ignore_sensor_regexp'] as $bi) { if (preg_match($bi, $sensor_descr) > 0) { print_debug("Skipped by regexp: {$bi}, {$sensor_descr} "); return FALSE; } } if (!is_null($limit_low_warn) && !is_null($limit_high_warn) && $limit_low_warn > $limit_high_warn) { // Fix high/low thresholds (i.e. on negative numbers) list($limit_high_warn, $limit_low_warn) = array($limit_low_warn, $limit_high_warn); } if (dbFetchCell('SELECT COUNT(`sensor_id`) FROM `sensors` WHERE `poller_type`= ? AND `sensor_class` = ? AND `device_id` = ? AND `sensor_type` = ? AND `sensor_index` = ?', array($poller_type, $class, $device['device_id'], $type, $index)) == '0') { if (!$limit_high) { $limit_high = sensor_limit_high($class, $value, $limit_auto); } if (!$limit_low) { $limit_low = sensor_limit_low($class, $value, $limit_auto); } if (!is_null($limit_low) && !is_null($limit_high) && $limit_low > $limit_high) { // Fix high/low thresholds (i.e. on negative numbers) list($limit_high, $limit_low) = array($limit_low, $limit_high); print_debug("High/low limits swapped."); } $sensor_insert = array('poller_type' => $poller_type, 'sensor_class' => $class, 'device_id' => $device['device_id'], 'sensor_index' => $index, 'sensor_type' => $type); foreach ($param_main as $key => $column) { $sensor_insert[$column] = ${$key}; } foreach ($param_limits as $key => $column) { // Convert strings/numbers to (float) or to array('NULL') ${$key} = ${$key} === NULL ? array('NULL') : (double) ${$key}; $sensor_insert[$column] = ${$key}; } foreach ($param_opt as $key) { if (is_null(${$key})) { ${$key} = array('NULL'); } $sensor_insert[$key] = ${$key}; } $sensor_id = dbInsert($sensor_insert, 'sensors'); $state_insert = array('sensor_id' => $sensor_id, 'sensor_value' => $value, 'sensor_polled' => 'NOW()'); dbInsert($state_insert, 'sensors-state'); print_debug("( {$sensor_id} inserted )"); echo '+'; log_event("Sensor added: {$class} {$type} {$index} {$sensor_descr}", $device, 'sensor', $sensor_id); } else { $sensor_entry = dbFetchRow("SELECT * FROM `sensors` WHERE `sensor_class` = ? AND `device_id` = ? AND `sensor_type` = ? AND `sensor_index` = ?", array($class, $device['device_id'], $type, $index)); // Limits if (!$sensor_entry['sensor_custom_limit']) { if (!is_numeric($limit_high)) { if ($sensor_entry['sensor_limit'] !== '') { // Calculate a reasonable limit $limit_high = sensor_limit_high($class, $value, $limit_auto); } else { // Use existing limit. (this is wrong! --mike) $limit_high = $sensor_entry['sensor_limit']; } } if (!is_numeric($limit_low)) { if ($sensor_entry['sensor_limit_low'] !== '') { // Calculate a reasonable limit $limit_low = sensor_limit_low($class, $value, $limit_auto); } else { // Use existing limit. (this is wrong! --mike) $limit_low = $sensor_entry['sensor_limit_low']; } } // Fix high/low thresholds (i.e. on negative numbers) if (!is_null($limit_low) && !is_null($limit_high) && $limit_low > $limit_high) { list($limit_high, $limit_low) = array($limit_low, $limit_high); print_debug("High/low limits swapped."); } // Update limits $update = array(); $update_msg = array(); $debug_msg = 'Current sensor value: "' . $value . '", scale: "' . $scale . '"' . PHP_EOL; foreach ($param_limits as $key => $column) { // $key - param name, $$key - param value, $column - column name in DB for $key $debug_msg .= ' ' . $key . ': "' . $sensor_entry[$column] . '" -> "' . ${$key} . '"' . PHP_EOL; //convert strings/numbers to identical type (float) or to array('NULL') for correct comparison ${$key} = ${$key} === NULL ? array('NULL') : (double) ${$key}; $sensor_entry[$column] = $sensor_entry[$column] === NULL ? array('NULL') : (double) $sensor_entry[$column]; if (float_cmp(${$key}, $sensor_entry[$column], 0.1) !== 0) { $update[$column] = ${$key}; $update_msg[] = $key . ' -> "' . (is_array(${$key}) ? 'NULL' : ${$key}) . '"'; } } if (count($update)) { echo "L"; print_debug($debug_msg); log_event('Sensor updated (limits): ' . implode(', ', $update_msg), $device, 'sensor', $sensor_entry['sensor_id']); $updated = dbUpdate($update, 'sensors', '`sensor_id` = ?', array($sensor_entry['sensor_id'])); } } $update = array(); foreach ($param_main as $key => $column) { if (float_cmp(${$key}, $sensor_entry[$column]) !== 0) { $update[$column] = ${$key}; } } foreach ($param_opt as $key) { if (${$key} != $sensor_entry[$key]) { $update[$key] = ${$key}; } } if (count($update)) { $updated = dbUpdate($update, 'sensors', '`sensor_id` = ?', array($sensor_entry['sensor_id'])); echo 'U'; log_event("Sensor updated: {$class} {$type} {$index} {$sensor_descr}", $device, 'sensor', $sensor_entry['sensor_id']); } else { echo '.'; } } $valid[$class][$type][$index] = 1; }
function discover_sensor(&$valid, $class, $device, $oid, $index, $type, $sensor_descr, $scale = 1, $current = NULL, $options = array(), $poller_type = 'snmp') { global $config; // If this is actually a status indicator, pass it off to discover_status() then return. if ($class == 'state' || $class == 'status') { print_debug("Redirect call to discover_status()."); $return = discover_status($device, $oid, $index, $type, $sensor_descr, $current, $options, $poller_type); return $return; } // Init main $param_main = array('oid' => 'sensor_oid', 'sensor_descr' => 'sensor_descr', 'scale' => 'sensor_multiplier'); // Init numeric values if (!is_numeric($scale) || $scale == 0) { $scale = 1; } // Skip discovery sensor if value not numeric or null (default) if ($current !== NULL) { // Some retarded devices report data with spaces and commas // STRING: " 20,4" $current = snmp_fix_numeric($current); } if (is_numeric($current)) { $f2c = FALSE; if ($class == 'temperature') { // This is weird hardcode for convert Fahrenheit to Celsius foreach (array(1, 0.1) as $scale_f2c) { if (float_cmp($scale, $scale_f2c * 5 / 9) === 0) { //$scale = $scale_tmp; $f2c = TRUE; break; } } } if ($f2c) { $current = f2c($current * $scale_f2c); print_debug('TEMPERATURE sensor: Fahrenheit -> Celsius'); } else { $current *= $scale; } } else { if ($current !== NULL) { print_debug("Sensor skipped by not numeric value: {$current}, {$sensor_descr} "); return FALSE; } } $param_limits = array('limit_high' => 'sensor_limit', 'limit_high_warn' => 'sensor_limit_warn', 'limit_low' => 'sensor_limit_low', 'limit_low_warn' => 'sensor_limit_low_warn'); foreach ($param_limits as $key => $column) { ${$key} = is_numeric($options[$key]) ? $options[$key] : NULL; } // Init optional $param_opt = array('entPhysicalIndex', 'entPhysicalClass', 'entPhysicalIndex_measured', 'measured_class', 'measured_entity'); foreach ($param_opt as $key) { ${$key} = $options[$key] ? $options[$key] : NULL; } print_debug("发现传感器: {$class}, " . $device['hostname'] . ", {$oid}, {$index}, {$type}, {$sensor_descr}, SCALE: {$scale}, LIMITS: ({$limit_low}, {$limit_low_warn}, {$limit_high_warn}, {$limit_high}), CURRENT: {$current}, {$poller_type}, {$entPhysicalIndex}, {$entPhysicalClass}"); // Check sensor ignore filters foreach ($config['ignore_sensor'] as $bi) { if (strcasecmp($bi, $sensor_descr) == 0) { print_debug("Skipped by equals: {$bi}, {$sensor_descr} "); return FALSE; } } foreach ($config['ignore_sensor_string'] as $bi) { if (stripos($sensor_descr, $bi) !== FALSE) { print_debug("Skipped by strpos: {$bi}, {$sensor_descr} "); return FALSE; } } foreach ($config['ignore_sensor_regexp'] as $bi) { if (preg_match($bi, $sensor_descr) > 0) { print_debug("Skipped by regexp: {$bi}, {$sensor_descr} "); return FALSE; } } if (!is_null($limit_low_warn) && !is_null($limit_high_warn) && $limit_low_warn > $limit_high_warn) { // Fix high/low thresholds (i.e. on negative numbers) list($limit_high_warn, $limit_low_warn) = array($limit_low_warn, $limit_high_warn); } if (dbFetchCell('SELECT COUNT(`sensor_id`) FROM `sensors` WHERE `poller_type`= ? AND `sensor_class` = ? AND `device_id` = ? AND `sensor_type` = ? AND `sensor_index` = ?', array($poller_type, $class, $device['device_id'], $type, $index)) == '0') { if (!$limit_high) { $limit_high = sensor_limit_high($class, $current); } if (!$limit_low) { $limit_low = sensor_limit_low($class, $current); } if (!is_null($limit_low) && !is_null($limit_high) && $limit_low > $limit_high) { // Fix high/low thresholds (i.e. on negative numbers) list($limit_high, $limit_low) = array($limit_low, $limit_high); print_debug("High/low limits swapped."); } $sensor_insert = array('poller_type' => $poller_type, 'sensor_class' => $class, 'device_id' => $device['device_id'], 'sensor_index' => $index, 'sensor_type' => $type); foreach ($param_main as $key => $column) { $sensor_insert[$column] = ${$key}; } foreach ($param_limits as $key => $column) { // Convert strings/numbers to (float) or to array('NULL') ${$key} = ${$key} === NULL ? array('NULL') : (double) ${$key}; $sensor_insert[$column] = ${$key}; } foreach ($param_opt as $key) { if (is_null(${$key})) { ${$key} = array('NULL'); } $sensor_insert[$key] = ${$key}; } $sensor_id = dbInsert($sensor_insert, 'sensors'); $state_insert = array('sensor_id' => $sensor_id, 'sensor_value' => $current, 'sensor_polled' => 'NOW()'); dbInsert($state_insert, 'sensors-state'); print_debug("( {$sensor_id} inserted )"); echo "+"; if ($poller_type != 'ipmi') { // Suppress events for IPMI, see: http://jira.observium.org/browse/OBSERVIUM-959 log_event("传感器已添加: {$class} {$type} {$index} {$sensor_descr}", $device, 'sensor', $sensor_id); } } else { $sensor_entry = dbFetchRow("SELECT * FROM `sensors` WHERE `sensor_class` = ? AND `device_id` = ? AND `sensor_type` = ? AND `sensor_index` = ?", array($class, $device['device_id'], $type, $index)); // Limits if (!$sensor_entry['sensor_custom_limit']) { if (!is_numeric($limit_high) && !is_numeric($limit_low)) { if ($sensor_entry['sensor_limit'] !== '') { // Calculate a reasonable limit $limit_high = sensor_limit_high($class, $current); } else { // Use existing limit. (this is wrong! --mike) $limit_high = $sensor_entry['sensor_limit']; } if ($sensor_entry['sensor_limit_low'] !== '') { // Calculate a reasonable limit $limit_low = sensor_limit_low($class, $current); } else { // Use existing limit. (this is wrong! --mike) $limit_low = $sensor_entry['sensor_limit_low']; } } // Fix high/low thresholds (i.e. on negative numbers) if (!is_null($limit_low) && !is_null($limit_high) && $limit_low > $limit_high) { list($limit_high, $limit_low) = array($limit_low, $limit_high); print_debug("High/low limits swapped."); } // Update limits $update = array(); $update_msg = array(); $debug_msg = 'Current sensor value: "' . $current . '", scale: "' . $scale . '"' . PHP_EOL; foreach ($param_limits as $key => $column) { // $key - param name, $$key - param value, $column - column name in DB for $key $debug_msg .= ' ' . $key . ': "' . $sensor_entry[$column] . '" -> "' . ${$key} . '"' . PHP_EOL; //convert strings/numbers to identical type (float) or to array('NULL') for correct comparison ${$key} = ${$key} === NULL ? array('NULL') : (double) ${$key}; $sensor_entry[$column] = $sensor_entry[$column] === NULL ? array('NULL') : (double) $sensor_entry[$column]; if (float_cmp(${$key}, $sensor_entry[$column], 0.1) !== 0) { $update[$column] = ${$key}; $update_msg[] = $key . ' -> "' . (is_array(${$key}) ? 'NULL' : ${$key}) . '"'; } } if (count($update)) { echo "L"; print_debug($debug_msg); log_event('传感器已更新(限制): ' . implode(', ', $update_msg), $device, 'sensor', $sensor_entry['sensor_id']); $updated = dbUpdate($update, 'sensors', '`sensor_id` = ?', array($sensor_entry['sensor_id'])); } } $update = array(); foreach ($param_main as $key => $column) { if (float_cmp(${$key}, $sensor_entry[$column]) !== 0) { $update[$column] = ${$key}; } } foreach ($param_opt as $key) { if (${$key} != $sensor_entry[$key]) { $update[$key] = ${$key}; } } if (count($update)) { $updated = dbUpdate($update, 'sensors', '`sensor_id` = ?', array($sensor_entry['sensor_id'])); echo "U"; log_event("传感器已更新: {$class} {$type} {$index} {$sensor_descr}", $device, 'sensor', $sensor_entry['sensor_id']); } else { echo "."; } } $valid[$class][$type][$index] = 1; }