2010-02-15 21:34:57 +01:00
|
|
|
package PandoraFMS::GIS;
|
|
|
|
##########################################################################
|
|
|
|
# GIS Pandora FMS functions.
|
|
|
|
# Pandora FMS. the Flexible Monitoring System. http://www.pandorafms.org
|
|
|
|
##########################################################################
|
2023-07-03 17:20:25 +02:00
|
|
|
# Copyright (c) 2005-2023 Pandora FMS
|
2010-02-15 21:34:57 +01:00
|
|
|
#
|
|
|
|
# This program is free software; you can redistribute it and/or
|
|
|
|
# modify it under the terms of the GNU Lesser General Public License
|
|
|
|
# as published by the Free Software Foundation; version 2
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with this program; if not, write to the Free Software
|
|
|
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
##########################################################################
|
|
|
|
|
|
|
|
=head1 NAME
|
|
|
|
|
|
|
|
PandoraFMS::GIS - Geographic Information System functions of Pandora FMS
|
|
|
|
|
|
|
|
=head1 VERSION
|
|
|
|
|
|
|
|
Version 3.1
|
|
|
|
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
|
|
|
|
use PandoraFMS::GIS;
|
|
|
|
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
|
|
|
|
This module contains the B<GIS> (Geographic Information System) related functions of B<Pandora FMS>
|
|
|
|
|
|
|
|
=head2 Interface
|
|
|
|
Exported Functions:
|
|
|
|
|
|
|
|
=over
|
|
|
|
|
|
|
|
=item * C<distance_moved>
|
|
|
|
|
2018-07-05 15:01:23 +02:00
|
|
|
=item * C<get_geoip_info>
|
2010-02-15 21:34:57 +01:00
|
|
|
|
|
|
|
=back
|
|
|
|
|
|
|
|
=head1 METHODS
|
|
|
|
|
|
|
|
=cut
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
use warnings;
|
2018-07-05 15:01:23 +02:00
|
|
|
use Geo::IP;
|
2010-02-15 21:34:57 +01:00
|
|
|
|
2010-05-19 Ramon Novoa <rnovoa@artica.es>
* lib/PandoraFMS/SNMPServer.pm, lib/PandoraFMS/Config.pm,
lib/PandoraFMS/Server.pm, lib/PandoraFMS/NetworkServer.pm,
lib/PandoraFMS/GIS.pm, lib/PandoraFMS/WMIServer.pm,
lib/PandoraFMS/PluginServer.pm, lib/PandoraFMS/ProducerConsumerServer.pm,
lib/PandoraFMS/PredictionServer.pm, lib/PandoraFMS/Core.pm,
lib/PandoraFMS/ReconServer.pm, lib/PandoraFMS/DataServer.pm,
bin/pandora_server, util/pandora_db.pl, util/gpx2pandora_agent_data.pl,
util/pandora_manage.pl, util/pandora_dbstress.pl: Added the default library path
used by RPM and DEB packages.
git-svn-id: https://svn.code.sf.net/p/pandora/code/trunk@2755 c3f86ba8-e40f-0410-aaad-9ba5e7f4b01f
2010-05-19 18:59:00 +02:00
|
|
|
# Default lib dir for RPM and DEB packages
|
2021-04-15 17:56:02 +02:00
|
|
|
BEGIN { push @INC, '/usr/lib/perl5'; }
|
2010-05-19 Ramon Novoa <rnovoa@artica.es>
* lib/PandoraFMS/SNMPServer.pm, lib/PandoraFMS/Config.pm,
lib/PandoraFMS/Server.pm, lib/PandoraFMS/NetworkServer.pm,
lib/PandoraFMS/GIS.pm, lib/PandoraFMS/WMIServer.pm,
lib/PandoraFMS/PluginServer.pm, lib/PandoraFMS/ProducerConsumerServer.pm,
lib/PandoraFMS/PredictionServer.pm, lib/PandoraFMS/Core.pm,
lib/PandoraFMS/ReconServer.pm, lib/PandoraFMS/DataServer.pm,
bin/pandora_server, util/pandora_db.pl, util/gpx2pandora_agent_data.pl,
util/pandora_manage.pl, util/pandora_dbstress.pl: Added the default library path
used by RPM and DEB packages.
git-svn-id: https://svn.code.sf.net/p/pandora/code/trunk@2755 c3f86ba8-e40f-0410-aaad-9ba5e7f4b01f
2010-05-19 18:59:00 +02:00
|
|
|
|
2010-02-15 21:34:57 +01:00
|
|
|
use PandoraFMS::DB;
|
|
|
|
use PandoraFMS::Tools;
|
|
|
|
|
|
|
|
|
|
|
|
require Exporter;
|
|
|
|
|
|
|
|
our @ISA = ("Exporter");
|
|
|
|
our %EXPORT_TAGS = ( 'all' => [ qw( ) ] );
|
|
|
|
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
|
|
|
|
our @EXPORT = qw(
|
|
|
|
distance_moved
|
2018-07-05 15:01:23 +02:00
|
|
|
get_geoip_info
|
2010-02-15 21:34:57 +01:00
|
|
|
);
|
|
|
|
# Some intenrnal constants
|
|
|
|
|
|
|
|
my $earth_radius_in_meters = 6372797.560856;
|
|
|
|
my $pi = 4*atan2(1,1);
|
|
|
|
my $to_radians= $pi/180;
|
|
|
|
my $to_half_radians= $pi/360;
|
|
|
|
my $to_degrees = 180/$pi;
|
|
|
|
|
|
|
|
##########################################################################
|
|
|
|
=head2 C<< distance_moved (I<$pa_config>, I<$last_longitude>, I<$last_latitude>, I<$last_altitude>, I<$longitude>, I<$latitude>, I<$altitude>) >>
|
|
|
|
|
|
|
|
Measures the distance between the last position and the previous one taking in acount the earth curvature
|
|
|
|
The distance is based on Havesine formula and so far doesn't take on account the altitude
|
|
|
|
|
|
|
|
B<< Refferences (I<Theory>): >>
|
|
|
|
* L<http://franchu.net/2007/11/16/gis-calculo-de-distancias-sobre-la-tierra/>
|
|
|
|
* L<http://en.wikipedia.org/wiki/Haversine_formula>
|
|
|
|
|
|
|
|
B<< References (I<C implementation>): >>
|
|
|
|
* L<http://blog.julien.cayzac.name/2008/10/arc-and-distance-between-two-points-on.html>
|
|
|
|
|
|
|
|
=cut
|
|
|
|
##########################################################################
|
|
|
|
sub distance_moved ($$$$$$$) {
|
2015-02-13 12:36:05 +01:00
|
|
|
my ($pa_config, $last_longitude, $last_latitude, $last_altitude,
|
|
|
|
$longitude, $latitude, $altitude) = @_;
|
|
|
|
|
|
|
|
if (!is_numeric($last_longitude) &&
|
|
|
|
!is_numeric($longitude) &&
|
|
|
|
!is_numeric($last_latitude) &&
|
|
|
|
!is_numeric($latitude)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-02-15 21:34:57 +01:00
|
|
|
my $long_difference = $last_longitude - $longitude;
|
|
|
|
my $lat_difference = $last_latitude - $latitude;
|
|
|
|
#my $alt_difference = $last_altitude - $altitude;
|
2015-02-13 12:36:05 +01:00
|
|
|
|
|
|
|
|
|
|
|
my $long_aux = sin ($long_difference * $to_half_radians);
|
|
|
|
my $lat_aux = sin ($lat_difference * $to_half_radians);
|
2010-02-15 21:34:57 +01:00
|
|
|
$long_aux *= $long_aux;
|
|
|
|
$lat_aux *= $lat_aux;
|
|
|
|
# Temporary value to make sorter the asin formula.
|
2015-02-13 12:36:05 +01:00
|
|
|
my $asinaux = sqrt($lat_aux +
|
|
|
|
cos($last_latitude*$to_radians) * cos($latitude * $to_radians) * $long_aux );
|
2010-02-15 21:34:57 +01:00
|
|
|
# Assure the aux value is not greater than 1
|
2015-02-13 12:36:05 +01:00
|
|
|
if ($asinaux > 1) {
|
|
|
|
$asinaux = 1;
|
|
|
|
}
|
2010-02-15 21:34:57 +01:00
|
|
|
# We use: asin(x) = atan2(x, sqrt(1-x*x))
|
|
|
|
my $dist_in_rad = 2.0 * atan2($asinaux, sqrt (1 - $asinaux * $asinaux));
|
|
|
|
my $dist_in_meters = $earth_radius_in_meters * $dist_in_rad;
|
2015-02-13 12:36:05 +01:00
|
|
|
|
|
|
|
logger($pa_config,
|
|
|
|
"Distance moved:" . $dist_in_meters ." meters", 10);
|
|
|
|
|
2010-02-15 21:34:57 +01:00
|
|
|
return $dist_in_meters;
|
|
|
|
}
|
|
|
|
|
|
|
|
##########################################################################
|
2018-07-05 15:01:23 +02:00
|
|
|
=head2 C<< get_geoip_info (I<$pa_config>, I<$address>, I<$dispersion>) >>
|
2010-02-15 21:34:57 +01:00
|
|
|
|
2018-07-05 15:01:23 +02:00
|
|
|
Get GIS information from the MaxMind GeoIP database on file using Geo::IP module
|
2010-02-15 21:34:57 +01:00
|
|
|
|
2018-07-05 15:01:23 +02:00
|
|
|
B<Returns>: I<undef> if there is not information available or a B<hash ref> with:
|
2010-02-15 21:34:57 +01:00
|
|
|
* I<longitude>
|
|
|
|
* I<latitude>
|
|
|
|
|
|
|
|
=cut
|
|
|
|
##########################################################################
|
2018-07-05 15:01:23 +02:00
|
|
|
sub get_geoip_info {
|
|
|
|
my ($pa_config, $address) = @_;
|
|
|
|
|
|
|
|
# Return undef if feature is not activated
|
|
|
|
return undef unless ($pa_config->{'activate_gis'} && $pa_config->{'recon_reverse_geolocation_file'} ne '');
|
|
|
|
|
|
|
|
my $record = undef;
|
|
|
|
eval {
|
|
|
|
local $SIG{__DIE__};
|
2018-07-11 18:56:49 +02:00
|
|
|
my $gi = Geo::IP->open($pa_config->{'recon_reverse_geolocation_file'}, GEOIP_STANDARD);
|
2018-07-05 15:01:23 +02:00
|
|
|
die("Cannot load the geoip file \"" . $pa_config->{'recon_reverse_geolocation_file'} . "\".\n") unless defined($gi);
|
|
|
|
$record = $gi->record_by_addr($address);
|
|
|
|
};
|
|
|
|
if ($@) {
|
|
|
|
logger($pa_config, "Error giving coordinates to IP: $address. $@", 8);
|
2010-02-15 21:34:57 +01:00
|
|
|
}
|
2018-07-05 15:01:23 +02:00
|
|
|
return undef unless defined($record);
|
2010-02-15 21:34:57 +01:00
|
|
|
|
2018-07-05 15:01:23 +02:00
|
|
|
# Fuzzy position filter
|
|
|
|
my ($longitude, $latitude) = get_random_close_point (
|
|
|
|
$pa_config, $record->longitude, $record->latitude
|
|
|
|
);
|
2010-02-15 21:34:57 +01:00
|
|
|
|
2018-07-05 15:01:23 +02:00
|
|
|
return {
|
|
|
|
"longitude" => $longitude,
|
|
|
|
"latitude" => $latitude
|
|
|
|
};
|
2010-02-15 21:34:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
##########################################################################
|
|
|
|
=head2 C<< get_random_close_point(I<$pa_config>, I<$center_longitude>, I<$center_latitude>) >>
|
|
|
|
|
|
|
|
Gets the B<Longitude> and the B<Laitiutde> of a random point in the surroundings of the
|
|
|
|
coordintaes received (I<$center_longitude>, I<$center_latitude>).
|
|
|
|
|
|
|
|
Returns C<< (I<$longitude>, I<$laitiutde>) >>
|
|
|
|
=cut
|
|
|
|
##########################################################################
|
|
|
|
sub get_random_close_point ($$$) {
|
|
|
|
my ($pa_config, $center_longitude, $center_latitude) = @_;
|
2018-07-05 15:01:23 +02:00
|
|
|
|
|
|
|
return ($center_longitude, $center_latitude) if ($pa_config->{'recon_location_scatter_radius'} == 0);
|
|
|
|
|
2010-02-15 21:34:57 +01:00
|
|
|
my $sign = int rand(2);
|
|
|
|
my $longitude = ($sign*(-1)+(1-$sign)) * rand($pa_config->{'recon_location_scatter_radius'}/$earth_radius_in_meters)*$to_degrees;
|
|
|
|
logger($pa_config,"Longitude random offset '$longitude' ", 8);
|
|
|
|
$longitude += $center_longitude;
|
|
|
|
logger($pa_config,"Longitude with random offset '$longitude' ", 8);
|
|
|
|
$sign = int rand(2);
|
|
|
|
my $latitude = ($sign*(-1)+(1-$sign)) * rand($pa_config->{'recon_location_scatter_radius'}/$earth_radius_in_meters)*$to_degrees;
|
|
|
|
logger($pa_config,"Longitude random offset '$latitude' ", 8);
|
|
|
|
$latitude += $center_latitude;
|
|
|
|
logger($pa_config,"Latiitude with random offset '$latitude' ", 8);
|
|
|
|
return ($longitude, $latitude);
|
|
|
|
}
|
|
|
|
|
|
|
|
# End of function declaration
|
|
|
|
# End of defined Code
|
|
|
|
|
|
|
|
1;
|
|
|
|
__END__
|
|
|
|
|
|
|
|
=head1 DEPENDENCIES
|
|
|
|
|
2018-07-05 15:01:23 +02:00
|
|
|
L<PandoraFMS::DB>, L<PandoraFMS::Tools>, L<Geo::IP>
|
2010-02-15 21:34:57 +01:00
|
|
|
|
|
|
|
=head1 LICENSE
|
|
|
|
|
|
|
|
This is released under the GNU Lesser General Public License.
|
|
|
|
|
|
|
|
=head1 SEE ALSO
|
|
|
|
|
|
|
|
L<PandoraFMS::DB>, L<PandoraFMS::Tools>
|
|
|
|
|
|
|
|
=head1 COPYRIGHT
|
|
|
|
|
2023-07-03 17:20:25 +02:00
|
|
|
Copyright (c) 2005-2023 Pandora FMS
|
2010-02-15 21:34:57 +01:00
|
|
|
|
|
|
|
=cut
|