mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-03-12 22:56:34 +00:00
fhem.de/stats added to contrib
git-svn-id: https://svn.fhem.de/fhem/trunk@2258 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
651837960f
commit
941ee44da8
fhem
FHEM
contrib/statistics
@ -25,8 +25,6 @@ package main;
|
|||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
use Config;
|
use Config;
|
||||||
use HTTP::Request::Common qw(POST);
|
|
||||||
use LWP::UserAgent;
|
|
||||||
|
|
||||||
sub CommandFheminfo($$);
|
sub CommandFheminfo($$);
|
||||||
|
|
||||||
@ -57,6 +55,21 @@ CommandFheminfo($$)
|
|||||||
my $name = "fheminfo";
|
my $name = "fheminfo";
|
||||||
my %info;
|
my %info;
|
||||||
|
|
||||||
|
my $module;
|
||||||
|
my $err = "Missing perl module '$module'. Please install this module first.";
|
||||||
|
my $err;
|
||||||
|
$module = "HTTP::Request::Common";
|
||||||
|
if(!checkModule($module)) {
|
||||||
|
Log 1, "$name $err";
|
||||||
|
return $err;
|
||||||
|
}
|
||||||
|
|
||||||
|
$module = "LWP::UserAgent";
|
||||||
|
if(!checkModule($module)) {
|
||||||
|
Log 1, "$name $err";
|
||||||
|
return $err;
|
||||||
|
}
|
||||||
|
|
||||||
return "Unknown argument $args[0], usage: fheminfo [send]" if(@args && lc($args[0]) ne "send");
|
return "Unknown argument $args[0], usage: fheminfo [send]" if(@args && lc($args[0]) ne "send");
|
||||||
|
|
||||||
my $branch = $DISTRIB_BRANCH;
|
my $branch = $DISTRIB_BRANCH;
|
||||||
@ -125,7 +138,7 @@ CommandFheminfo($$)
|
|||||||
$ret = $str;
|
$ret = $str;
|
||||||
|
|
||||||
if(@args != 0 && $args[0] eq "send") {
|
if(@args != 0 && $args[0] eq "send") {
|
||||||
my $uri = "http://fhem.de/stats/statistics.cgi";
|
my $uri = "http://192.168.1.5/cgi/statistics.cgi";
|
||||||
my $req = HTTP::Request->new("POST",$uri);
|
my $req = HTTP::Request->new("POST",$uri);
|
||||||
$req->content_type("application/x-www-form-urlencoded");
|
$req->content_type("application/x-www-form-urlencoded");
|
||||||
my $contInfo;
|
my $contInfo;
|
||||||
@ -200,6 +213,17 @@ sub checkConfigFile($) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub checkModule($) {
|
||||||
|
my $module = shift;
|
||||||
|
eval("use $module");
|
||||||
|
|
||||||
|
if($@) {
|
||||||
|
return(0);
|
||||||
|
} else {
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
||||||
=pod
|
=pod
|
||||||
|
8
fhem/contrib/statistics/data/README_GeoLiteCity.dat
Normal file
8
fhem/contrib/statistics/data/README_GeoLiteCity.dat
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
Please download 'GeoLiteCity' package from
|
||||||
|
http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
|
||||||
|
and gunzip in this directory.
|
||||||
|
|
||||||
|
The GeoLite databases are distributed under the Creative Commons
|
||||||
|
Attribution-ShareAlike 3.0 Unported License.
|
||||||
|
|
||||||
|
For more Informations, visit: http://dev.maxmind.com/geoip/geolite
|
@ -0,0 +1,4 @@
|
|||||||
|
The file "fhem_statistics_db.sqlite" is the database for the delivered statistics.
|
||||||
|
|
||||||
|
The database file is created automatically.
|
||||||
|
|
5937
fhem/contrib/statistics/lib/Geo/IP.pm
Normal file
5937
fhem/contrib/statistics/lib/Geo/IP.pm
Normal file
File diff suppressed because it is too large
Load Diff
752
fhem/contrib/statistics/lib/Geo/IP/Record.pm
Normal file
752
fhem/contrib/statistics/lib/Geo/IP/Record.pm
Normal file
@ -0,0 +1,752 @@
|
|||||||
|
package Geo::IP::Record;
|
||||||
|
|
||||||
|
use Geo::IP; #
|
||||||
|
|
||||||
|
use vars qw/$pp/;
|
||||||
|
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
# here are the missing functions if the C API is used
|
||||||
|
sub latitude {
|
||||||
|
my $gir = shift;
|
||||||
|
return sprintf( "%.4f", $gir->_latitude );
|
||||||
|
}
|
||||||
|
|
||||||
|
sub longitude {
|
||||||
|
my $gir = shift;
|
||||||
|
return sprintf( "%.4f", $gir->_longitude );
|
||||||
|
}
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
$pp = !defined(&Geo::IP::Record::city)
|
||||||
|
|| $Geo::IP::GEOIP_PP_ONLY;
|
||||||
|
}
|
||||||
|
|
||||||
|
eval <<'__PP__' if $pp;
|
||||||
|
|
||||||
|
for ( qw: country_code country_code3 country_name
|
||||||
|
region region_name city
|
||||||
|
postal_code dma_code area_code
|
||||||
|
continent_code metro_code : ) {
|
||||||
|
|
||||||
|
no strict qw/ refs /;
|
||||||
|
no warnings qw/ redefine /;
|
||||||
|
my $m = $_; # looks bogus, but it is not! it is a copy not a alias
|
||||||
|
*$_ = sub { $_[0]->{$m} };
|
||||||
|
}
|
||||||
|
|
||||||
|
# for the case warnings are globaly enabled with perl -w and the CAPI is absent
|
||||||
|
no warnings qw/ redefine /;
|
||||||
|
|
||||||
|
sub longitude {sprintf('%.4f', $_[0]->{longitude})}
|
||||||
|
sub latitude {sprintf('%.4f', $_[0]->{latitude})}
|
||||||
|
|
||||||
|
{
|
||||||
|
my $TIME_ZONE;
|
||||||
|
|
||||||
|
local $_ = <DATA>; # skip first line
|
||||||
|
while (<DATA>) {
|
||||||
|
chomp;
|
||||||
|
next if /^\s*$/;
|
||||||
|
my ( $country, $region, $timezone ) = split /\t/;
|
||||||
|
$TIME_ZONE->{$country}->{ $region || '' } = $timezone;
|
||||||
|
}
|
||||||
|
|
||||||
|
# called from Geo::IP
|
||||||
|
sub _time_zone {
|
||||||
|
my ( undef, $country, $region ) = @_;
|
||||||
|
return undef unless $country;
|
||||||
|
return undef unless defined $TIME_ZONE->{$country};
|
||||||
|
$region ||= '';
|
||||||
|
return
|
||||||
|
defined $TIME_ZONE->{$country}->{$region}
|
||||||
|
? $TIME_ZONE->{$country}->{$region}
|
||||||
|
: $TIME_ZONE->{$country}->{''};
|
||||||
|
}
|
||||||
|
sub time_zone {
|
||||||
|
my ( $self ) = @_;
|
||||||
|
my ( $country, $region ) = ( $self->country_code, $self->region );
|
||||||
|
return $self->_time_zone( $country, $region );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__PP__
|
||||||
|
1;
|
||||||
|
__DATA__
|
||||||
|
country region timezone
|
||||||
|
US AL America/Chicago
|
||||||
|
US AK America/Anchorage
|
||||||
|
US AZ America/Phoenix
|
||||||
|
US AR America/Chicago
|
||||||
|
US CA America/Los_Angeles
|
||||||
|
US CO America/Denver
|
||||||
|
US CT America/New_York
|
||||||
|
US DE America/New_York
|
||||||
|
US DC America/New_York
|
||||||
|
US FL America/New_York
|
||||||
|
US GA America/New_York
|
||||||
|
US HI Pacific/Honolulu
|
||||||
|
US ID America/Denver
|
||||||
|
US IL America/Chicago
|
||||||
|
US IN America/Indianapolis
|
||||||
|
US IA America/Chicago
|
||||||
|
US KS America/Chicago
|
||||||
|
US KY America/New_York
|
||||||
|
US LA America/Chicago
|
||||||
|
US ME America/New_York
|
||||||
|
US MD America/New_York
|
||||||
|
US MA America/New_York
|
||||||
|
US MI America/New_York
|
||||||
|
US MN America/Chicago
|
||||||
|
US MS America/Chicago
|
||||||
|
US MO America/Chicago
|
||||||
|
US MT America/Denver
|
||||||
|
US NE America/Chicago
|
||||||
|
US NV America/Los_Angeles
|
||||||
|
US NH America/New_York
|
||||||
|
US NJ America/New_York
|
||||||
|
US NM America/Denver
|
||||||
|
US NY America/New_York
|
||||||
|
US NC America/New_York
|
||||||
|
US ND America/Chicago
|
||||||
|
US OH America/New_York
|
||||||
|
US OK America/Chicago
|
||||||
|
US OR America/Los_Angeles
|
||||||
|
US PA America/New_York
|
||||||
|
US RI America/New_York
|
||||||
|
US SC America/New_York
|
||||||
|
US SD America/Chicago
|
||||||
|
US TN America/Chicago
|
||||||
|
US TX America/Chicago
|
||||||
|
US UT America/Denver
|
||||||
|
US VT America/New_York
|
||||||
|
US VA America/New_York
|
||||||
|
US WA America/Los_Angeles
|
||||||
|
US WV America/New_York
|
||||||
|
US WI America/Chicago
|
||||||
|
US WY America/Denver
|
||||||
|
CA AB America/Edmonton
|
||||||
|
CA BC America/Vancouver
|
||||||
|
CA MB America/Winnipeg
|
||||||
|
CA NB America/Halifax
|
||||||
|
CA NL America/St_Johns
|
||||||
|
CA NT America/Yellowknife
|
||||||
|
CA NS America/Halifax
|
||||||
|
CA NU America/Rankin_Inlet
|
||||||
|
CA ON America/Rainy_River
|
||||||
|
CA PE America/Halifax
|
||||||
|
CA QC America/Montreal
|
||||||
|
CA SK America/Regina
|
||||||
|
CA YT America/Whitehorse
|
||||||
|
AU 01 Australia/Canberra
|
||||||
|
AU 02 Australia/NSW
|
||||||
|
AU 03 Australia/North
|
||||||
|
AU 04 Australia/Queensland
|
||||||
|
AU 05 Australia/South
|
||||||
|
AU 06 Australia/Tasmania
|
||||||
|
AU 07 Australia/Victoria
|
||||||
|
AU 08 Australia/West
|
||||||
|
AS US/Samoa
|
||||||
|
CI Africa/Abidjan
|
||||||
|
GH Africa/Accra
|
||||||
|
DZ Africa/Algiers
|
||||||
|
ER Africa/Asmera
|
||||||
|
ML Africa/Bamako
|
||||||
|
CF Africa/Bangui
|
||||||
|
GM Africa/Banjul
|
||||||
|
GW Africa/Bissau
|
||||||
|
CG Africa/Brazzaville
|
||||||
|
BI Africa/Bujumbura
|
||||||
|
EG Africa/Cairo
|
||||||
|
MA Africa/Casablanca
|
||||||
|
GN Africa/Conakry
|
||||||
|
SN Africa/Dakar
|
||||||
|
DJ Africa/Djibouti
|
||||||
|
SL Africa/Freetown
|
||||||
|
BW Africa/Gaborone
|
||||||
|
ZW Africa/Harare
|
||||||
|
ZA Africa/Johannesburg
|
||||||
|
UG Africa/Kampala
|
||||||
|
SD Africa/Khartoum
|
||||||
|
RW Africa/Kigali
|
||||||
|
NG Africa/Lagos
|
||||||
|
GA Africa/Libreville
|
||||||
|
TG Africa/Lome
|
||||||
|
AO Africa/Luanda
|
||||||
|
ZM Africa/Lusaka
|
||||||
|
GQ Africa/Malabo
|
||||||
|
MZ Africa/Maputo
|
||||||
|
LS Africa/Maseru
|
||||||
|
SZ Africa/Mbabane
|
||||||
|
SO Africa/Mogadishu
|
||||||
|
LR Africa/Monrovia
|
||||||
|
KE Africa/Nairobi
|
||||||
|
TD Africa/Ndjamena
|
||||||
|
NE Africa/Niamey
|
||||||
|
MR Africa/Nouakchott
|
||||||
|
BF Africa/Ouagadougou
|
||||||
|
ST Africa/Sao_Tome
|
||||||
|
LY Africa/Tripoli
|
||||||
|
TN Africa/Tunis
|
||||||
|
AI America/Anguilla
|
||||||
|
AG America/Antigua
|
||||||
|
AW America/Aruba
|
||||||
|
BB America/Barbados
|
||||||
|
BZ America/Belize
|
||||||
|
CO America/Bogota
|
||||||
|
VE America/Caracas
|
||||||
|
KY America/Cayman
|
||||||
|
CR America/Costa_Rica
|
||||||
|
DM America/Dominica
|
||||||
|
SV America/El_Salvador
|
||||||
|
GD America/Grenada
|
||||||
|
FR Europe/Paris
|
||||||
|
GP America/Guadeloupe
|
||||||
|
GT America/Guatemala
|
||||||
|
GY America/Guyana
|
||||||
|
CU America/Havana
|
||||||
|
JM America/Jamaica
|
||||||
|
BO America/La_Paz
|
||||||
|
PE America/Lima
|
||||||
|
NI America/Managua
|
||||||
|
MQ America/Martinique
|
||||||
|
UY America/Montevideo
|
||||||
|
MS America/Montserrat
|
||||||
|
BS America/Nassau
|
||||||
|
PA America/Panama
|
||||||
|
SR America/Paramaribo
|
||||||
|
PR America/Puerto_Rico
|
||||||
|
KN America/St_Kitts
|
||||||
|
LC America/St_Lucia
|
||||||
|
VC America/St_Vincent
|
||||||
|
HN America/Tegucigalpa
|
||||||
|
YE Asia/Aden
|
||||||
|
JO Asia/Amman
|
||||||
|
TM Asia/Ashgabat
|
||||||
|
IQ Asia/Baghdad
|
||||||
|
BH Asia/Bahrain
|
||||||
|
AZ Asia/Baku
|
||||||
|
TH Asia/Bangkok
|
||||||
|
LB Asia/Beirut
|
||||||
|
KG Asia/Bishkek
|
||||||
|
BN Asia/Brunei
|
||||||
|
IN Asia/Calcutta
|
||||||
|
MN Asia/Choibalsan
|
||||||
|
LK Asia/Colombo
|
||||||
|
BD Asia/Dhaka
|
||||||
|
AE Asia/Dubai
|
||||||
|
TJ Asia/Dushanbe
|
||||||
|
HK Asia/Hong_Kong
|
||||||
|
TR Asia/Istanbul
|
||||||
|
IL Asia/Jerusalem
|
||||||
|
AF Asia/Kabul
|
||||||
|
PK Asia/Karachi
|
||||||
|
NP Asia/Katmandu
|
||||||
|
KW Asia/Kuwait
|
||||||
|
MO Asia/Macao
|
||||||
|
PH Asia/Manila
|
||||||
|
OM Asia/Muscat
|
||||||
|
CY Asia/Nicosia
|
||||||
|
KP Asia/Pyongyang
|
||||||
|
QA Asia/Qatar
|
||||||
|
MM Asia/Rangoon
|
||||||
|
SA Asia/Riyadh
|
||||||
|
KR Asia/Seoul
|
||||||
|
SG Asia/Singapore
|
||||||
|
TW Asia/Taipei
|
||||||
|
GE Asia/Tbilisi
|
||||||
|
BT Asia/Thimphu
|
||||||
|
JP Asia/Tokyo
|
||||||
|
LA Asia/Vientiane
|
||||||
|
AM Asia/Yerevan
|
||||||
|
BM Atlantic/Bermuda
|
||||||
|
CV Atlantic/Cape_Verde
|
||||||
|
FO Atlantic/Faeroe
|
||||||
|
IS Atlantic/Reykjavik
|
||||||
|
GS Atlantic/South_Georgia
|
||||||
|
SH Atlantic/St_Helena
|
||||||
|
CL Chile/Continental
|
||||||
|
NL Europe/Amsterdam
|
||||||
|
AD Europe/Andorra
|
||||||
|
GR Europe/Athens
|
||||||
|
YU Europe/Belgrade
|
||||||
|
DE Europe/Berlin
|
||||||
|
SK Europe/Bratislava
|
||||||
|
BE Europe/Brussels
|
||||||
|
RO Europe/Bucharest
|
||||||
|
HU Europe/Budapest
|
||||||
|
DK Europe/Copenhagen
|
||||||
|
IE Europe/Dublin
|
||||||
|
GI Europe/Gibraltar
|
||||||
|
FI Europe/Helsinki
|
||||||
|
SI Europe/Ljubljana
|
||||||
|
GB Europe/London
|
||||||
|
LU Europe/Luxembourg
|
||||||
|
MT Europe/Malta
|
||||||
|
BY Europe/Minsk
|
||||||
|
MC Europe/Monaco
|
||||||
|
NO Europe/Oslo
|
||||||
|
CZ Europe/Prague
|
||||||
|
LV Europe/Riga
|
||||||
|
IT Europe/Rome
|
||||||
|
SM Europe/San_Marino
|
||||||
|
BA Europe/Sarajevo
|
||||||
|
MK Europe/Skopje
|
||||||
|
BG Europe/Sofia
|
||||||
|
SE Europe/Stockholm
|
||||||
|
EE Europe/Tallinn
|
||||||
|
AL Europe/Tirane
|
||||||
|
LI Europe/Vaduz
|
||||||
|
VA Europe/Vatican
|
||||||
|
AT Europe/Vienna
|
||||||
|
LT Europe/Vilnius
|
||||||
|
PL Europe/Warsaw
|
||||||
|
HR Europe/Zagreb
|
||||||
|
IR Asia/Tehran
|
||||||
|
MG Indian/Antananarivo
|
||||||
|
CX Indian/Christmas
|
||||||
|
CC Indian/Cocos
|
||||||
|
KM Indian/Comoro
|
||||||
|
MV Indian/Maldives
|
||||||
|
MU Indian/Mauritius
|
||||||
|
YT Indian/Mayotte
|
||||||
|
RE Indian/Reunion
|
||||||
|
FJ Pacific/Fiji
|
||||||
|
TV Pacific/Funafuti
|
||||||
|
GU Pacific/Guam
|
||||||
|
NR Pacific/Nauru
|
||||||
|
NU Pacific/Niue
|
||||||
|
NF Pacific/Norfolk
|
||||||
|
PW Pacific/Palau
|
||||||
|
PN Pacific/Pitcairn
|
||||||
|
CK Pacific/Rarotonga
|
||||||
|
WS Pacific/Samoa
|
||||||
|
KI Pacific/Tarawa
|
||||||
|
TO Pacific/Tongatapu
|
||||||
|
WF Pacific/Wallis
|
||||||
|
TZ Africa/Dar_es_Salaam
|
||||||
|
VN Asia/Phnom_Penh
|
||||||
|
KH Asia/Phnom_Penh
|
||||||
|
CM Africa/Lagos
|
||||||
|
DO America/Santo_Domingo
|
||||||
|
ET Africa/Addis_Ababa
|
||||||
|
FX Europe/Paris
|
||||||
|
HT America/Port-au-Prince
|
||||||
|
CH Europe/Zurich
|
||||||
|
AN America/Curacao
|
||||||
|
BJ Africa/Porto-Novo
|
||||||
|
EH Africa/El_Aaiun
|
||||||
|
FK Atlantic/Stanley
|
||||||
|
GF America/Cayenne
|
||||||
|
IO Indian/Chagos
|
||||||
|
MD Europe/Chisinau
|
||||||
|
MP Pacific/Saipan
|
||||||
|
MW Africa/Blantyre
|
||||||
|
NA Africa/Windhoek
|
||||||
|
NC Pacific/Noumea
|
||||||
|
PG Pacific/Port_Moresby
|
||||||
|
PM America/Miquelon
|
||||||
|
PS Asia/Gaza
|
||||||
|
PY America/Asuncion
|
||||||
|
SB Pacific/Guadalcanal
|
||||||
|
SC Indian/Mahe
|
||||||
|
SJ Arctic/Longyearbyen
|
||||||
|
SY Asia/Damascus
|
||||||
|
TC America/Grand_Turk
|
||||||
|
TF Indian/Kerguelen
|
||||||
|
TK Pacific/Fakaofo
|
||||||
|
TT America/Port_of_Spain
|
||||||
|
VG America/Tortola
|
||||||
|
VI America/St_Thomas
|
||||||
|
VU Pacific/Efate
|
||||||
|
RS Europe/Belgrade
|
||||||
|
ME Europe/Podgorica
|
||||||
|
AX Europe/Mariehamn
|
||||||
|
GG Europe/Guernsey
|
||||||
|
IM Europe/Isle_of_Man
|
||||||
|
JE Europe/Jersey
|
||||||
|
BL America/St_Barthelemy
|
||||||
|
MF America/Marigot
|
||||||
|
AR 01 America/Argentina/Buenos_Aires
|
||||||
|
AR 02 America/Argentina/Catamarca
|
||||||
|
AR 03 America/Argentina/Tucuman
|
||||||
|
AR 04 America/Argentina/Rio_Gallegos
|
||||||
|
AR 05 America/Argentina/Cordoba
|
||||||
|
AR 06 America/Argentina/Tucuman
|
||||||
|
AR 07 America/Argentina/Buenos_Aires
|
||||||
|
AR 08 America/Argentina/Buenos_Aires
|
||||||
|
AR 09 America/Argentina/Tucuman
|
||||||
|
AR 10 America/Argentina/Jujuy
|
||||||
|
AR 11 America/Argentina/San_Luis
|
||||||
|
AR 12 America/Argentina/La_Rioja
|
||||||
|
AR 13 America/Argentina/Mendoza
|
||||||
|
AR 14 America/Argentina/Buenos_Aires
|
||||||
|
AR 15 America/Argentina/San_Luis
|
||||||
|
AR 16 America/Argentina/Buenos_Aires
|
||||||
|
AR 17 America/Argentina/Salta
|
||||||
|
AR 18 America/Argentina/San_Juan
|
||||||
|
AR 19 America/Argentina/San_Luis
|
||||||
|
AR 20 America/Argentina/Rio_Gallegos
|
||||||
|
AR 21 America/Argentina/Buenos_Aires
|
||||||
|
AR 22 America/Argentina/Catamarca
|
||||||
|
AR 23 America/Argentina/Ushuaia
|
||||||
|
AR 24 America/Argentina/Tucuman
|
||||||
|
BR 01 America/Rio_Branco
|
||||||
|
BR 02 America/Maceio
|
||||||
|
BR 03 America/Sao_Paulo
|
||||||
|
BR 04 America/Manaus
|
||||||
|
BR 05 America/Bahia
|
||||||
|
BR 06 America/Fortaleza
|
||||||
|
BR 07 America/Sao_Paulo
|
||||||
|
BR 08 America/Sao_Paulo
|
||||||
|
BR 11 America/Campo_Grande
|
||||||
|
BR 13 America/Belem
|
||||||
|
BR 14 America/Cuiaba
|
||||||
|
BR 15 America/Sao_Paulo
|
||||||
|
BR 16 America/Belem
|
||||||
|
BR 17 America/Recife
|
||||||
|
BR 18 America/Sao_Paulo
|
||||||
|
BR 20 America/Fortaleza
|
||||||
|
BR 21 America/Sao_Paulo
|
||||||
|
BR 22 America/Recife
|
||||||
|
BR 23 America/Sao_Paulo
|
||||||
|
BR 24 America/Porto_Velho
|
||||||
|
BR 25 America/Boa_Vista
|
||||||
|
BR 26 America/Sao_Paulo
|
||||||
|
BR 27 America/Sao_Paulo
|
||||||
|
BR 28 America/Maceio
|
||||||
|
BR 29 America/Sao_Paulo
|
||||||
|
BR 30 America/Recife
|
||||||
|
BR 31 America/Araguaina
|
||||||
|
CD 02 Africa/Kinshasa
|
||||||
|
CD 05 Africa/Lubumbashi
|
||||||
|
CD 06 Africa/Kinshasa
|
||||||
|
CD 08 Africa/Kinshasa
|
||||||
|
CD 10 Africa/Lubumbashi
|
||||||
|
CD 11 Africa/Lubumbashi
|
||||||
|
CD 12 Africa/Lubumbashi
|
||||||
|
CN 01 Asia/Shanghai
|
||||||
|
CN 02 Asia/Shanghai
|
||||||
|
CN 03 Asia/Shanghai
|
||||||
|
CN 04 Asia/Shanghai
|
||||||
|
CN 05 Asia/Harbin
|
||||||
|
CN 06 Asia/Chongqing
|
||||||
|
CN 07 Asia/Shanghai
|
||||||
|
CN 08 Asia/Harbin
|
||||||
|
CN 09 Asia/Shanghai
|
||||||
|
CN 10 Asia/Shanghai
|
||||||
|
CN 11 Asia/Chongqing
|
||||||
|
CN 12 Asia/Shanghai
|
||||||
|
CN 13 Asia/Urumqi
|
||||||
|
CN 14 Asia/Chongqing
|
||||||
|
CN 15 Asia/Chongqing
|
||||||
|
CN 16 Asia/Chongqing
|
||||||
|
CN 18 Asia/Chongqing
|
||||||
|
CN 19 Asia/Harbin
|
||||||
|
CN 20 Asia/Harbin
|
||||||
|
CN 21 Asia/Chongqing
|
||||||
|
CN 22 Asia/Harbin
|
||||||
|
CN 23 Asia/Shanghai
|
||||||
|
CN 24 Asia/Chongqing
|
||||||
|
CN 25 Asia/Shanghai
|
||||||
|
CN 26 Asia/Chongqing
|
||||||
|
CN 28 Asia/Shanghai
|
||||||
|
CN 29 Asia/Chongqing
|
||||||
|
CN 30 Asia/Chongqing
|
||||||
|
CN 31 Asia/Chongqing
|
||||||
|
CN 32 Asia/Chongqing
|
||||||
|
CN 33 Asia/Chongqing
|
||||||
|
EC 01 Pacific/Galapagos
|
||||||
|
EC 02 America/Guayaquil
|
||||||
|
EC 03 America/Guayaquil
|
||||||
|
EC 04 America/Guayaquil
|
||||||
|
EC 05 America/Guayaquil
|
||||||
|
EC 06 America/Guayaquil
|
||||||
|
EC 07 America/Guayaquil
|
||||||
|
EC 08 America/Guayaquil
|
||||||
|
EC 09 America/Guayaquil
|
||||||
|
EC 10 America/Guayaquil
|
||||||
|
EC 11 America/Guayaquil
|
||||||
|
EC 12 America/Guayaquil
|
||||||
|
EC 13 America/Guayaquil
|
||||||
|
EC 14 America/Guayaquil
|
||||||
|
EC 15 America/Guayaquil
|
||||||
|
EC 17 America/Guayaquil
|
||||||
|
EC 18 America/Guayaquil
|
||||||
|
EC 19 America/Guayaquil
|
||||||
|
EC 20 America/Guayaquil
|
||||||
|
EC 22 America/Guayaquil
|
||||||
|
ES 07 Europe/Madrid
|
||||||
|
ES 27 Europe/Madrid
|
||||||
|
ES 29 Europe/Madrid
|
||||||
|
ES 31 Europe/Madrid
|
||||||
|
ES 32 Europe/Madrid
|
||||||
|
ES 34 Europe/Madrid
|
||||||
|
ES 39 Europe/Madrid
|
||||||
|
ES 51 Africa/Ceuta
|
||||||
|
ES 52 Europe/Madrid
|
||||||
|
ES 53 Atlantic/Canary
|
||||||
|
ES 54 Europe/Madrid
|
||||||
|
ES 55 Europe/Madrid
|
||||||
|
ES 56 Europe/Madrid
|
||||||
|
ES 57 Europe/Madrid
|
||||||
|
ES 58 Europe/Madrid
|
||||||
|
ES 59 Europe/Madrid
|
||||||
|
ES 60 Europe/Madrid
|
||||||
|
GL 01 America/Thule
|
||||||
|
GL 02 America/Godthab
|
||||||
|
GL 03 America/Godthab
|
||||||
|
ID 01 Asia/Pontianak
|
||||||
|
ID 02 Asia/Makassar
|
||||||
|
ID 03 Asia/Jakarta
|
||||||
|
ID 04 Asia/Jakarta
|
||||||
|
ID 05 Asia/Jakarta
|
||||||
|
ID 06 Asia/Jakarta
|
||||||
|
ID 07 Asia/Jakarta
|
||||||
|
ID 08 Asia/Jakarta
|
||||||
|
ID 09 Asia/Jayapura
|
||||||
|
ID 10 Asia/Jakarta
|
||||||
|
ID 11 Asia/Pontianak
|
||||||
|
ID 12 Asia/Makassar
|
||||||
|
ID 13 Asia/Makassar
|
||||||
|
ID 14 Asia/Makassar
|
||||||
|
ID 15 Asia/Jakarta
|
||||||
|
ID 16 Asia/Makassar
|
||||||
|
ID 17 Asia/Makassar
|
||||||
|
ID 18 Asia/Makassar
|
||||||
|
ID 19 Asia/Pontianak
|
||||||
|
ID 20 Asia/Makassar
|
||||||
|
ID 21 Asia/Makassar
|
||||||
|
ID 22 Asia/Makassar
|
||||||
|
ID 23 Asia/Makassar
|
||||||
|
ID 24 Asia/Jakarta
|
||||||
|
ID 25 Asia/Pontianak
|
||||||
|
ID 26 Asia/Pontianak
|
||||||
|
ID 30 Asia/Jakarta
|
||||||
|
ID 31 Asia/Makassar
|
||||||
|
ID 33 Asia/Jakarta
|
||||||
|
KZ 01 Asia/Almaty
|
||||||
|
KZ 02 Asia/Almaty
|
||||||
|
KZ 03 Asia/Qyzylorda
|
||||||
|
KZ 04 Asia/Aqtobe
|
||||||
|
KZ 05 Asia/Qyzylorda
|
||||||
|
KZ 06 Asia/Aqtau
|
||||||
|
KZ 07 Asia/Oral
|
||||||
|
KZ 08 Asia/Qyzylorda
|
||||||
|
KZ 09 Asia/Aqtau
|
||||||
|
KZ 10 Asia/Qyzylorda
|
||||||
|
KZ 11 Asia/Almaty
|
||||||
|
KZ 12 Asia/Qyzylorda
|
||||||
|
KZ 13 Asia/Aqtobe
|
||||||
|
KZ 14 Asia/Qyzylorda
|
||||||
|
KZ 15 Asia/Almaty
|
||||||
|
KZ 16 Asia/Aqtobe
|
||||||
|
KZ 17 Asia/Almaty
|
||||||
|
MX 01 America/Mexico_City
|
||||||
|
MX 02 America/Tijuana
|
||||||
|
MX 03 America/Hermosillo
|
||||||
|
MX 04 America/Merida
|
||||||
|
MX 05 America/Mexico_City
|
||||||
|
MX 06 America/Chihuahua
|
||||||
|
MX 07 America/Monterrey
|
||||||
|
MX 08 America/Mexico_City
|
||||||
|
MX 09 America/Mexico_City
|
||||||
|
MX 10 America/Mazatlan
|
||||||
|
MX 11 America/Mexico_City
|
||||||
|
MX 12 America/Mexico_City
|
||||||
|
MX 13 America/Mexico_City
|
||||||
|
MX 14 America/Mazatlan
|
||||||
|
MX 15 America/Chihuahua
|
||||||
|
MX 16 America/Mexico_City
|
||||||
|
MX 17 America/Mexico_City
|
||||||
|
MX 18 America/Mazatlan
|
||||||
|
MX 19 America/Monterrey
|
||||||
|
MX 20 America/Mexico_City
|
||||||
|
MX 21 America/Mexico_City
|
||||||
|
MX 22 America/Mexico_City
|
||||||
|
MX 23 America/Cancun
|
||||||
|
MX 24 America/Mexico_City
|
||||||
|
MX 25 America/Mazatlan
|
||||||
|
MX 26 America/Hermosillo
|
||||||
|
MX 27 America/Merida
|
||||||
|
MX 28 America/Monterrey
|
||||||
|
MX 29 America/Mexico_City
|
||||||
|
MX 30 America/Mexico_City
|
||||||
|
MX 31 America/Merida
|
||||||
|
MX 32 America/Monterrey
|
||||||
|
MY 01 Asia/Kuala_Lumpur
|
||||||
|
MY 02 Asia/Kuala_Lumpur
|
||||||
|
MY 03 Asia/Kuala_Lumpur
|
||||||
|
MY 04 Asia/Kuala_Lumpur
|
||||||
|
MY 05 Asia/Kuala_Lumpur
|
||||||
|
MY 06 Asia/Kuala_Lumpur
|
||||||
|
MY 07 Asia/Kuala_Lumpur
|
||||||
|
MY 08 Asia/Kuala_Lumpur
|
||||||
|
MY 09 Asia/Kuala_Lumpur
|
||||||
|
MY 11 Asia/Kuching
|
||||||
|
MY 12 Asia/Kuala_Lumpur
|
||||||
|
MY 13 Asia/Kuala_Lumpur
|
||||||
|
MY 14 Asia/Kuala_Lumpur
|
||||||
|
MY 15 Asia/Kuching
|
||||||
|
MY 16 Asia/Kuching
|
||||||
|
NZ 85 Pacific/Auckland
|
||||||
|
NZ E7 Pacific/Auckland
|
||||||
|
NZ E8 Pacific/Auckland
|
||||||
|
NZ E9 Pacific/Auckland
|
||||||
|
NZ F1 Pacific/Auckland
|
||||||
|
NZ F2 Pacific/Auckland
|
||||||
|
NZ F3 Pacific/Auckland
|
||||||
|
NZ F4 Pacific/Auckland
|
||||||
|
NZ F5 Pacific/Auckland
|
||||||
|
NZ F7 Pacific/Chatham
|
||||||
|
NZ F8 Pacific/Auckland
|
||||||
|
NZ F9 Pacific/Auckland
|
||||||
|
NZ G1 Pacific/Auckland
|
||||||
|
NZ G2 Pacific/Auckland
|
||||||
|
NZ G3 Pacific/Auckland
|
||||||
|
PT 02 Europe/Lisbon
|
||||||
|
PT 03 Europe/Lisbon
|
||||||
|
PT 04 Europe/Lisbon
|
||||||
|
PT 05 Europe/Lisbon
|
||||||
|
PT 06 Europe/Lisbon
|
||||||
|
PT 07 Europe/Lisbon
|
||||||
|
PT 08 Europe/Lisbon
|
||||||
|
PT 09 Europe/Lisbon
|
||||||
|
PT 10 Atlantic/Madeira
|
||||||
|
PT 11 Europe/Lisbon
|
||||||
|
PT 13 Europe/Lisbon
|
||||||
|
PT 14 Europe/Lisbon
|
||||||
|
PT 16 Europe/Lisbon
|
||||||
|
PT 17 Europe/Lisbon
|
||||||
|
PT 18 Europe/Lisbon
|
||||||
|
PT 19 Europe/Lisbon
|
||||||
|
PT 20 Europe/Lisbon
|
||||||
|
PT 21 Europe/Lisbon
|
||||||
|
PT 22 Europe/Lisbon
|
||||||
|
RU 01 Europe/Volgograd
|
||||||
|
RU 02 Asia/Irkutsk
|
||||||
|
RU 03 Asia/Novokuznetsk
|
||||||
|
RU 04 Asia/Novosibirsk
|
||||||
|
RU 05 Asia/Vladivostok
|
||||||
|
RU 06 Europe/Moscow
|
||||||
|
RU 07 Europe/Volgograd
|
||||||
|
RU 08 Europe/Samara
|
||||||
|
RU 09 Europe/Moscow
|
||||||
|
RU 10 Europe/Moscow
|
||||||
|
RU 11 Asia/Irkutsk
|
||||||
|
RU 13 Asia/Yekaterinburg
|
||||||
|
RU 14 Asia/Irkutsk
|
||||||
|
RU 15 Asia/Anadyr
|
||||||
|
RU 16 Europe/Samara
|
||||||
|
RU 17 Europe/Volgograd
|
||||||
|
RU 18 Asia/Krasnoyarsk
|
||||||
|
RU 20 Asia/Irkutsk
|
||||||
|
RU 21 Europe/Moscow
|
||||||
|
RU 22 Europe/Volgograd
|
||||||
|
RU 23 Europe/Kaliningrad
|
||||||
|
RU 24 Europe/Volgograd
|
||||||
|
RU 25 Europe/Moscow
|
||||||
|
RU 26 Asia/Kamchatka
|
||||||
|
RU 27 Europe/Volgograd
|
||||||
|
RU 28 Europe/Moscow
|
||||||
|
RU 29 Asia/Novokuznetsk
|
||||||
|
RU 30 Asia/Vladivostok
|
||||||
|
RU 31 Asia/Krasnoyarsk
|
||||||
|
RU 32 Asia/Omsk
|
||||||
|
RU 33 Asia/Yekaterinburg
|
||||||
|
RU 34 Asia/Yekaterinburg
|
||||||
|
RU 35 Asia/Yekaterinburg
|
||||||
|
RU 36 Asia/Anadyr
|
||||||
|
RU 37 Europe/Moscow
|
||||||
|
RU 38 Europe/Volgograd
|
||||||
|
RU 39 Asia/Krasnoyarsk
|
||||||
|
RU 40 Asia/Yekaterinburg
|
||||||
|
RU 41 Europe/Moscow
|
||||||
|
RU 42 Europe/Moscow
|
||||||
|
RU 43 Europe/Moscow
|
||||||
|
RU 44 Asia/Magadan
|
||||||
|
RU 45 Europe/Samara
|
||||||
|
RU 46 Europe/Samara
|
||||||
|
RU 47 Europe/Moscow
|
||||||
|
RU 48 Europe/Moscow
|
||||||
|
RU 49 Europe/Moscow
|
||||||
|
RU 50 Asia/Yekaterinburg
|
||||||
|
RU 51 Europe/Moscow
|
||||||
|
RU 52 Europe/Moscow
|
||||||
|
RU 53 Asia/Novosibirsk
|
||||||
|
RU 54 Asia/Omsk
|
||||||
|
RU 55 Europe/Samara
|
||||||
|
RU 56 Europe/Moscow
|
||||||
|
RU 57 Europe/Samara
|
||||||
|
RU 58 Asia/Yekaterinburg
|
||||||
|
RU 59 Asia/Vladivostok
|
||||||
|
RU 60 Europe/Kaliningrad
|
||||||
|
RU 61 Europe/Volgograd
|
||||||
|
RU 62 Europe/Moscow
|
||||||
|
RU 63 Asia/Yakutsk
|
||||||
|
RU 64 Asia/Sakhalin
|
||||||
|
RU 65 Europe/Samara
|
||||||
|
RU 66 Europe/Moscow
|
||||||
|
RU 67 Europe/Samara
|
||||||
|
RU 68 Europe/Volgograd
|
||||||
|
RU 69 Europe/Moscow
|
||||||
|
RU 70 Europe/Volgograd
|
||||||
|
RU 71 Asia/Yekaterinburg
|
||||||
|
RU 72 Europe/Moscow
|
||||||
|
RU 73 Europe/Samara
|
||||||
|
RU 74 Asia/Krasnoyarsk
|
||||||
|
RU 75 Asia/Novosibirsk
|
||||||
|
RU 76 Europe/Moscow
|
||||||
|
RU 77 Europe/Moscow
|
||||||
|
RU 78 Asia/Yekaterinburg
|
||||||
|
RU 79 Asia/Irkutsk
|
||||||
|
RU 80 Asia/Yekaterinburg
|
||||||
|
RU 81 Europe/Samara
|
||||||
|
RU 82 Asia/Irkutsk
|
||||||
|
RU 83 Europe/Moscow
|
||||||
|
RU 84 Europe/Volgograd
|
||||||
|
RU 85 Europe/Moscow
|
||||||
|
RU 86 Europe/Moscow
|
||||||
|
RU 87 Asia/Novosibirsk
|
||||||
|
RU 88 Europe/Moscow
|
||||||
|
RU 89 Asia/Vladivostok
|
||||||
|
UA 01 Europe/Kiev
|
||||||
|
UA 02 Europe/Kiev
|
||||||
|
UA 03 Europe/Uzhgorod
|
||||||
|
UA 04 Europe/Zaporozhye
|
||||||
|
UA 05 Europe/Zaporozhye
|
||||||
|
UA 06 Europe/Uzhgorod
|
||||||
|
UA 07 Europe/Zaporozhye
|
||||||
|
UA 08 Europe/Simferopol
|
||||||
|
UA 09 Europe/Kiev
|
||||||
|
UA 10 Europe/Zaporozhye
|
||||||
|
UA 11 Europe/Simferopol
|
||||||
|
UA 13 Europe/Kiev
|
||||||
|
UA 14 Europe/Zaporozhye
|
||||||
|
UA 15 Europe/Uzhgorod
|
||||||
|
UA 16 Europe/Zaporozhye
|
||||||
|
UA 17 Europe/Simferopol
|
||||||
|
UA 18 Europe/Zaporozhye
|
||||||
|
UA 19 Europe/Kiev
|
||||||
|
UA 20 Europe/Simferopol
|
||||||
|
UA 21 Europe/Kiev
|
||||||
|
UA 22 Europe/Uzhgorod
|
||||||
|
UA 23 Europe/Kiev
|
||||||
|
UA 24 Europe/Uzhgorod
|
||||||
|
UA 25 Europe/Uzhgorod
|
||||||
|
UA 26 Europe/Zaporozhye
|
||||||
|
UA 27 Europe/Kiev
|
||||||
|
UZ 01 Asia/Tashkent
|
||||||
|
UZ 02 Asia/Samarkand
|
||||||
|
UZ 03 Asia/Tashkent
|
||||||
|
UZ 06 Asia/Tashkent
|
||||||
|
UZ 07 Asia/Samarkand
|
||||||
|
UZ 08 Asia/Samarkand
|
||||||
|
UZ 09 Asia/Samarkand
|
||||||
|
UZ 10 Asia/Samarkand
|
||||||
|
UZ 12 Asia/Samarkand
|
||||||
|
UZ 13 Asia/Tashkent
|
||||||
|
UZ 14 Asia/Tashkent
|
||||||
|
TL Asia/Dili
|
||||||
|
PF Pacific/Marquesas
|
104
fhem/contrib/statistics/lib/Geo/IP/Record.pod
Normal file
104
fhem/contrib/statistics/lib/Geo/IP/Record.pod
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
Geo::IP::Record - Contains city information for GeoIP City Edition
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
use Geo::IP;
|
||||||
|
|
||||||
|
my $gi = Geo::IP->open("/usr/local/share/GeoIP/GeoIPCity.dat", GEOIP_STANDARD);
|
||||||
|
|
||||||
|
my $record = $gi->record_by_addr('24.24.24.24');
|
||||||
|
|
||||||
|
print $record->country_code,
|
||||||
|
$record->country_code3,
|
||||||
|
$record->country_name,
|
||||||
|
$record->region,
|
||||||
|
$record->region_name,
|
||||||
|
$record->city,
|
||||||
|
$record->postal_code,
|
||||||
|
$record->latitude,
|
||||||
|
$record->longitude,
|
||||||
|
$record->time_zone,
|
||||||
|
$record->area_code,
|
||||||
|
$record->continent_code,
|
||||||
|
$record->metro_code;
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
Geo::IP::Record represents objects containing location information
|
||||||
|
returned by the GeoIP City database. It works with both the
|
||||||
|
commercial GeoIP City and free GeoLite City databases.
|
||||||
|
|
||||||
|
=head1 OBJECT METHODS
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
=item $code = $record->country_code;
|
||||||
|
|
||||||
|
Returns the ISO 3166 country code from the location object.
|
||||||
|
|
||||||
|
=item $code3 = $record->country_code3;
|
||||||
|
|
||||||
|
Returns the ISO 3166 3 letter country code from the location object.
|
||||||
|
|
||||||
|
=item $name = $record->country_name;
|
||||||
|
|
||||||
|
Returns the country name from the location object.
|
||||||
|
|
||||||
|
=item $region = $record->region;
|
||||||
|
|
||||||
|
Returns the region code from the location object.
|
||||||
|
|
||||||
|
=item $region = $record->region_name;
|
||||||
|
|
||||||
|
Returns the region name from the location object.
|
||||||
|
|
||||||
|
=item $city = $record->city;
|
||||||
|
|
||||||
|
Returns the city from the location object.
|
||||||
|
|
||||||
|
=item $postal_code = $record->postal_code;
|
||||||
|
|
||||||
|
Returns the postal code from the location object.
|
||||||
|
|
||||||
|
=item $lat = $record->latitude;
|
||||||
|
|
||||||
|
Returns the latitude from the location object.
|
||||||
|
|
||||||
|
=item $lon = $record->longitude;
|
||||||
|
|
||||||
|
Returns the longitude from the location object.
|
||||||
|
|
||||||
|
=item $time_zone = $record->time_zone;
|
||||||
|
|
||||||
|
Returns the time zone from the location object.
|
||||||
|
|
||||||
|
=item $area_code = $record->area_code;
|
||||||
|
|
||||||
|
Returns the area code from the location object (for city-level US locations only)
|
||||||
|
|
||||||
|
=item $metro_code = $record->metro_code;
|
||||||
|
|
||||||
|
Returns the metro code from the location object (for city-level US locations only)
|
||||||
|
|
||||||
|
|
||||||
|
=item $continent_code = $record->continent_code;
|
||||||
|
|
||||||
|
Returns the continent code from the location object.
|
||||||
|
Possible continent codes are AF, AS, EU, NA, OC, SA for Africa, Asia, Europe, North America, Oceania and South America.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head1 VERSION
|
||||||
|
|
||||||
|
1.21
|
||||||
|
|
||||||
|
=head1 AUTHOR
|
||||||
|
|
||||||
|
Copyright (c) 2008, MaxMind LLC
|
||||||
|
|
||||||
|
All rights reserved. This package is free software; you can redistribute it
|
||||||
|
and/or modify it under the same terms as Perl itself.
|
||||||
|
|
||||||
|
=cut
|
400
fhem/contrib/statistics/lib/Geo/Mirror.pm
Normal file
400
fhem/contrib/statistics/lib/Geo/Mirror.pm
Normal file
@ -0,0 +1,400 @@
|
|||||||
|
package Geo::Mirror;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use vars qw($VERSION);
|
||||||
|
|
||||||
|
$VERSION = '1.01';
|
||||||
|
|
||||||
|
use constant PI => 3.14159265358979323846;
|
||||||
|
|
||||||
|
our (%lat, %lon, $geo_ip_pkg);
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
if (eval { require Geo::IP }) {
|
||||||
|
$geo_ip_pkg = "Geo::IP";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
require Geo::IP::PurePerl;
|
||||||
|
$geo_ip_pkg = "Geo::IP::PurePerl";
|
||||||
|
}
|
||||||
|
$geo_ip_pkg->import('GEOIP_STANDARD');
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
local $_;
|
||||||
|
while (<DATA>) {
|
||||||
|
my ($country, $lat, $lon) = split(':');
|
||||||
|
|
||||||
|
$lat{$country} = $lat;
|
||||||
|
$lon{$country} = $lon;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub new {
|
||||||
|
my ($class, %h) = @_;
|
||||||
|
my $self = \%h;
|
||||||
|
bless $self, $class;
|
||||||
|
$self->_init;
|
||||||
|
return $self;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _init {
|
||||||
|
my $self = shift;
|
||||||
|
my $mirror_file = $self->{mirror_file};
|
||||||
|
local $_;
|
||||||
|
open MIRROR, "$mirror_file" or die $!;
|
||||||
|
while(<MIRROR>) {
|
||||||
|
my ($url, $country, $fresh) = split(' ');
|
||||||
|
push @{$self->{mirror}->{$country}}, $url;
|
||||||
|
$self->{fresh}{$url} = $fresh || 0;
|
||||||
|
}
|
||||||
|
close MIRROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _random_mirror {
|
||||||
|
my ($self, $country, $fresh) = @_;
|
||||||
|
|
||||||
|
my @mirror = grep { $self->{fresh}{$_} >= $fresh } @{$self->{mirror}->{$country}};
|
||||||
|
|
||||||
|
my $num = scalar @mirror or return;
|
||||||
|
|
||||||
|
return $mirror[ rand($num) ];
|
||||||
|
}
|
||||||
|
|
||||||
|
sub find_mirror_by_country {
|
||||||
|
my ($self, $country, $fresh) = @_;
|
||||||
|
my $url;
|
||||||
|
|
||||||
|
$fresh ||= 0;
|
||||||
|
|
||||||
|
if (exists $self->{mirror}->{$country}) {
|
||||||
|
$url = $self->_random_mirror($country, $fresh);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$url) {
|
||||||
|
my $nearby = $self->{nearby_cache}->{$country} ||= $self->_find_nearby_countries($country);
|
||||||
|
foreach my $new_country (@$nearby) {
|
||||||
|
$url = $self->_random_mirror($new_country, $fresh) and last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $url;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub find_mirror_by_addr {
|
||||||
|
my ($self, $addr, $fresh) = @_;
|
||||||
|
|
||||||
|
unless($self->{gi}) {
|
||||||
|
if ($self->{database_file}) {
|
||||||
|
$self->{gi} = $geo_ip_pkg->open($self->{database_file}, GEOIP_STANDARD);
|
||||||
|
} else {
|
||||||
|
$self->{gi} = $geo_ip_pkg->new(GEOIP_STANDARD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# default to US if country not found
|
||||||
|
my $country = lc($self->{gi}->country_code_by_addr($addr)) || 'us';
|
||||||
|
$country = 'us' if $country eq '--';
|
||||||
|
return $self->find_mirror_by_country($country, $fresh);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _find_nearby_countries {
|
||||||
|
my ($self, $country) = @_;
|
||||||
|
|
||||||
|
my %distance = map { ($_, $self->_calculate_distance($country, $_)) } keys %{$self->{mirror}};
|
||||||
|
delete $distance{$country};
|
||||||
|
|
||||||
|
[ sort { $distance{$a} <=> $distance{$b} } keys %distance ];
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _calculate_distance {
|
||||||
|
my ($self, $country1, $country2) = @_;
|
||||||
|
|
||||||
|
my $lat_1 = $lat{$country1};
|
||||||
|
my $lat_2 = $lat{$country2};
|
||||||
|
my $lon_1 = $lon{$country1};
|
||||||
|
my $lon_2 = $lon{$country2};
|
||||||
|
|
||||||
|
# Convert all the degrees to radians
|
||||||
|
$lat_1 *= PI/180;
|
||||||
|
$lon_1 *= PI/180;
|
||||||
|
$lat_2 *= PI/180;
|
||||||
|
$lon_2 *= PI/180;
|
||||||
|
|
||||||
|
# Find the deltas
|
||||||
|
my $delta_lat = $lat_2 - $lat_1;
|
||||||
|
my $delta_lon = $lon_2 - $lon_1;
|
||||||
|
|
||||||
|
# Find the Great Circle distance
|
||||||
|
my $temp = sin($delta_lat/2.0)**2 + cos($lat_1) * cos($lat_2) * sin($delta_lon/2.0)**2;
|
||||||
|
return atan2(sqrt($temp),sqrt(1-$temp));
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
Geo::Mirror - Find closest Mirror
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
use Geo::Mirror;
|
||||||
|
|
||||||
|
my $gm = Geo::Mirror->new(mirror_file => '/path/to/mirrors.txt');
|
||||||
|
|
||||||
|
my $mirror = $gm->closest_mirror_by_country('us', $freshness); # $freshness optional, see description below
|
||||||
|
my $mirror = $gm->closest_mirror_by_addr('24.24.24.24', $freshness); # $freshness optional, see description below
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
This module finds the closest mirror for an IP address. It uses L<Geo::IP>
|
||||||
|
to identify the country that the IP address originated from. If
|
||||||
|
the country is not represented in the mirror list, then it finds the
|
||||||
|
closest country using a latitude/longitude table.
|
||||||
|
|
||||||
|
The mirror file should be a space separate list of URL, Country, and mirror freshness.
|
||||||
|
The mirror freshness is optional and can be used by user
|
||||||
|
request a mirror with a minimum freshness.
|
||||||
|
|
||||||
|
=head1 AUTHOR
|
||||||
|
|
||||||
|
Copyright (c) 2004, MaxMind LLC, support@maxmind.com
|
||||||
|
|
||||||
|
All rights reserved. This package is free software; you can redistribute it
|
||||||
|
and/or modify it under the same terms as Perl itself.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
__DATA__
|
||||||
|
af:33:65
|
||||||
|
al:41:20
|
||||||
|
dz:28:3
|
||||||
|
as:-14:-170
|
||||||
|
ad:42:1
|
||||||
|
ao:-12:18
|
||||||
|
ai:18:-63
|
||||||
|
aq:-90:0
|
||||||
|
ag:17:-61
|
||||||
|
ar:-34:-64
|
||||||
|
am:40:45
|
||||||
|
aw:12:-69
|
||||||
|
au:-27:133
|
||||||
|
at:47:13
|
||||||
|
az:40:47
|
||||||
|
bs:24:-76
|
||||||
|
bh:26:50
|
||||||
|
bd:24:90
|
||||||
|
bb:13:-59
|
||||||
|
by:53:28
|
||||||
|
be:50:4
|
||||||
|
bz:17:-88
|
||||||
|
bj:9:2
|
||||||
|
bm:32:-64
|
||||||
|
bt:27:90
|
||||||
|
bo:-17:-65
|
||||||
|
ba:44:18
|
||||||
|
bw:-22:24
|
||||||
|
bv:-54:3
|
||||||
|
br:-10:-55
|
||||||
|
io:-6:71
|
||||||
|
vg:18:-64
|
||||||
|
bg:43:25
|
||||||
|
bf:13:-2
|
||||||
|
bi:-3:30
|
||||||
|
kh:13:105
|
||||||
|
cm:6:12
|
||||||
|
ca:60:-95
|
||||||
|
cv:16:-24
|
||||||
|
ky:19:-80
|
||||||
|
cf:7:21
|
||||||
|
td:15:19
|
||||||
|
cl:-30:-71
|
||||||
|
cn:35:105
|
||||||
|
cx:-10:105
|
||||||
|
cc:-12:96
|
||||||
|
co:4:-72
|
||||||
|
km:-12:44
|
||||||
|
cd:0:25
|
||||||
|
cg:-1:15
|
||||||
|
ck:-21:-159
|
||||||
|
cr:10:-84
|
||||||
|
ci:8:-5
|
||||||
|
hr:45:15
|
||||||
|
cu:21:-80
|
||||||
|
cy:35:33
|
||||||
|
cz:49:15
|
||||||
|
dk:56:10
|
||||||
|
dj:11:43
|
||||||
|
dm:15:-61
|
||||||
|
do:19:-70
|
||||||
|
ec:-2:-77
|
||||||
|
eg:27:30
|
||||||
|
sv:13:-88
|
||||||
|
gq:2:10
|
||||||
|
er:15:39
|
||||||
|
ee:59:26
|
||||||
|
et:8:38
|
||||||
|
fk:-51:-59
|
||||||
|
fo:62:-7
|
||||||
|
fj:-18:175
|
||||||
|
fi:64:26
|
||||||
|
fr:46:2
|
||||||
|
gf:4:-53
|
||||||
|
pf:-15:-140
|
||||||
|
ga:-1:11
|
||||||
|
gm:13:-16
|
||||||
|
ge:42:43
|
||||||
|
de:51:9
|
||||||
|
eu:48:10
|
||||||
|
gh:8:-2
|
||||||
|
gi:36:-5
|
||||||
|
gr:39:22
|
||||||
|
gl:72:-40
|
||||||
|
gd:12:-61
|
||||||
|
gp:16:-61
|
||||||
|
gu:13:144
|
||||||
|
gt:15:-90
|
||||||
|
gn:11:-10
|
||||||
|
gw:12:-15
|
||||||
|
gy:5:-59
|
||||||
|
ht:19:-72
|
||||||
|
hm:-53:72
|
||||||
|
va:41:12
|
||||||
|
hn:15:-86
|
||||||
|
hk:22:114
|
||||||
|
hu:47:20
|
||||||
|
is:65:-18
|
||||||
|
in:20:77
|
||||||
|
id:-5:120
|
||||||
|
ir:32:53
|
||||||
|
iq:33:44
|
||||||
|
ie:53:-8
|
||||||
|
il:31:34
|
||||||
|
it:42:12
|
||||||
|
jm:18:-77
|
||||||
|
sj:71:-8
|
||||||
|
jp:36:138
|
||||||
|
jo:31:36
|
||||||
|
ke:1:38
|
||||||
|
ki:1:173
|
||||||
|
kp:40:127
|
||||||
|
kr:37:127
|
||||||
|
kw:29:45
|
||||||
|
kg:41:75
|
||||||
|
lv:57:25
|
||||||
|
lb:33:35
|
||||||
|
ls:-29:28
|
||||||
|
lr:6:-9
|
||||||
|
ly:25:17
|
||||||
|
li:47:9
|
||||||
|
lt:56:24
|
||||||
|
lu:49:6
|
||||||
|
mo:22:113
|
||||||
|
mk:41:22
|
||||||
|
mg:-20:47
|
||||||
|
mw:-13:34
|
||||||
|
my:2:112
|
||||||
|
mv:3:73
|
||||||
|
ml:17:-4
|
||||||
|
mt:35:14
|
||||||
|
mh:9:168
|
||||||
|
mq:14:-61
|
||||||
|
mr:20:-12
|
||||||
|
mu:-20:57
|
||||||
|
yt:-12:45
|
||||||
|
mx:23:-102
|
||||||
|
fm:6:158
|
||||||
|
mc:43:7
|
||||||
|
mn:46:105
|
||||||
|
ms:16:-62
|
||||||
|
ma:32:-5
|
||||||
|
mz:-18:35
|
||||||
|
na:-22:17
|
||||||
|
nr:-0:166
|
||||||
|
np:28:84
|
||||||
|
nl:52:5
|
||||||
|
an:12:-68
|
||||||
|
nc:-21:165
|
||||||
|
nz:-41:174
|
||||||
|
ni:13:-85
|
||||||
|
ne:16:8
|
||||||
|
ng:10:8
|
||||||
|
nu:-19:-169
|
||||||
|
nf:-29:167
|
||||||
|
mp:15:145
|
||||||
|
no:62:10
|
||||||
|
om:21:57
|
||||||
|
pk:30:70
|
||||||
|
pw:7:134
|
||||||
|
pa:9:-80
|
||||||
|
pg:-6:147
|
||||||
|
py:-23:-58
|
||||||
|
pe:-10:-76
|
||||||
|
ph:13:122
|
||||||
|
pn:-25:-130
|
||||||
|
pl:52:20
|
||||||
|
pt:39:-8
|
||||||
|
pr:18:-66
|
||||||
|
qa:25:51
|
||||||
|
re:-21:55
|
||||||
|
ro:46:25
|
||||||
|
ru:60:100
|
||||||
|
rw:-2:30
|
||||||
|
sh:-15:-5
|
||||||
|
kn:17:-62
|
||||||
|
lc:13:-60
|
||||||
|
pm:46:-56
|
||||||
|
vc:13:-61
|
||||||
|
ws:-13:-172
|
||||||
|
sm:43:12
|
||||||
|
st:1:7
|
||||||
|
sa:25:45
|
||||||
|
sn:14:-14
|
||||||
|
sc:-4:55
|
||||||
|
sl:8:-11
|
||||||
|
sg:1:103
|
||||||
|
sk:48:19
|
||||||
|
si:46:15
|
||||||
|
sb:-8:159
|
||||||
|
so:10:49
|
||||||
|
za:-29:24
|
||||||
|
gs:-54:-37
|
||||||
|
es:40:-4
|
||||||
|
lk:7:81
|
||||||
|
sd:15:30
|
||||||
|
sr:4:-56
|
||||||
|
sj:78:20
|
||||||
|
sz:-26:31
|
||||||
|
se:62:15
|
||||||
|
ch:47:8
|
||||||
|
sy:35:38
|
||||||
|
tj:39:71
|
||||||
|
tz:-6:35
|
||||||
|
th:15:100
|
||||||
|
tg:8:1
|
||||||
|
tk:-9:-172
|
||||||
|
to:-20:-175
|
||||||
|
tt:11:-61
|
||||||
|
tn:34:9
|
||||||
|
tr:39:35
|
||||||
|
tm:40:60
|
||||||
|
tc:21:-71
|
||||||
|
tv:-8:178
|
||||||
|
ug:1:32
|
||||||
|
ua:49:32
|
||||||
|
ae:24:54
|
||||||
|
gb:54:-2
|
||||||
|
us:38:-97
|
||||||
|
uy:-33:-56
|
||||||
|
uz:41:64
|
||||||
|
vu:-16:167
|
||||||
|
ve:8:-66
|
||||||
|
vn:16:106
|
||||||
|
vi:18:-64
|
||||||
|
wf:-13:-176
|
||||||
|
eh:24:-13
|
||||||
|
ye:15:48
|
||||||
|
yu:44:21
|
||||||
|
zm:-15:30
|
||||||
|
zw:-20:30
|
||||||
|
tw:23:121
|
681
fhem/contrib/statistics/statistics.cgi
Executable file
681
fhem/contrib/statistics/statistics.cgi
Executable file
@ -0,0 +1,681 @@
|
|||||||
|
#!/usr/bin/perl -w
|
||||||
|
################################################################
|
||||||
|
# $Id: $
|
||||||
|
# vim: ts=2:et
|
||||||
|
#
|
||||||
|
# (c) 2012 Copyright: Martin Fischer (m_fischer at gmx dot de)
|
||||||
|
# All rights reserved
|
||||||
|
#
|
||||||
|
# This script free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# any later version.
|
||||||
|
#
|
||||||
|
# The GNU General Public License can be found at
|
||||||
|
# http://www.gnu.org/copyleft/gpl.html.
|
||||||
|
# A copy is found in the textfile GPL.txt and important notices to the license
|
||||||
|
# from the author is found in LICENSE.txt distributed with these scripts.
|
||||||
|
#
|
||||||
|
# This script 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.
|
||||||
|
#
|
||||||
|
################################################################
|
||||||
|
|
||||||
|
use CGI qw(:standard Vars);
|
||||||
|
use CGI::Carp qw(warningsToBrowser fatalsToBrowser);
|
||||||
|
use DBI; #requires libdbd-sqlite3-perl
|
||||||
|
use lib "./lib";
|
||||||
|
use Geo::IP;
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
no warnings 'uninitialized';
|
||||||
|
|
||||||
|
sub createDB();
|
||||||
|
sub insertDB();
|
||||||
|
sub checkColumn($$);
|
||||||
|
sub getLocation($);
|
||||||
|
sub googleVisualizationLib($);
|
||||||
|
sub drawMarkersMap(@);
|
||||||
|
sub drawPieChart(@);
|
||||||
|
sub drawRegionsMap(@);
|
||||||
|
sub drawTable(@);
|
||||||
|
sub drawColumnChartTop10Modules(@);
|
||||||
|
sub drawColumnChartTop10ModDef(@);
|
||||||
|
sub drawBarChartModules(@);
|
||||||
|
sub viewStatistics();
|
||||||
|
|
||||||
|
# cascading style sheet
|
||||||
|
my $css = "http://fhem.de/../css/style.css";
|
||||||
|
|
||||||
|
# exclude modules from top 10 graph
|
||||||
|
my $excludeFromTop10modules = "at autocreate notify telnet weblink FileLog SUNRISE_EL";
|
||||||
|
my $excludeFromTop10definitions = "at autocreate notify telnet weblink FileLog SUNRISE_EL";
|
||||||
|
|
||||||
|
# geo ip database file from http://www.maxmind.com/download/geoip/database/
|
||||||
|
# should be updated once per month
|
||||||
|
my $geoIPDat = "./data/GeoLiteCity.dat";
|
||||||
|
|
||||||
|
# database
|
||||||
|
my $dbf = "./data/fhem_statistics_db.sqlite";
|
||||||
|
my $dsn = "dbi:SQLite:dbname=$dbf";
|
||||||
|
my $sth;
|
||||||
|
|
||||||
|
# fhem node
|
||||||
|
my $ua = $ENV{HTTP_USER_AGENT};
|
||||||
|
my $ip = $ENV{REMOTE_ADDR};
|
||||||
|
my %data = Vars();
|
||||||
|
|
||||||
|
# create database if not exists
|
||||||
|
createDB() if (! -e $dbf);
|
||||||
|
|
||||||
|
my $dbh = DBI->connect($dsn,"","", { RaiseError => 1, ShowErrorStatement => 1 }) ||
|
||||||
|
die "Cannot connect: $DBI::errstr";
|
||||||
|
|
||||||
|
if(index($ua,"Fhem") > -1) {
|
||||||
|
print header("application/x-www-form-urlencoded");
|
||||||
|
insertDB();
|
||||||
|
print "==> ok";
|
||||||
|
} else {
|
||||||
|
viewStatistics();
|
||||||
|
}
|
||||||
|
|
||||||
|
sub viewStatistics() {
|
||||||
|
my $visLib = googleVisualizationLib("'corechart','geochart','table'");
|
||||||
|
my $cOS = drawPieChart("nodes","os","Operating System",400,300,"chart_os");
|
||||||
|
my $cArch = drawPieChart("nodes","arch","Architecture",400,300,"chart_arch");
|
||||||
|
my $cRelease = drawPieChart("nodes","release","FHEM Release",400,300,"chart_release");
|
||||||
|
my $cPerl = drawPieChart("nodes","perl","Perl Version",400,300,"chart_perl");
|
||||||
|
#my $cModulesTop10 = drawColumnChartTop10Modules("modules","modulestop10",,"Used",825,300,"chart_modulestop10");
|
||||||
|
#my $cModDefTop10 = drawColumnChartTop10ModDef("modules","definitions","Definitions",825,300,"chart_moddeftop10");
|
||||||
|
my $cModules = drawBarChartModules("modules","modules","Used","Definitions",825,600,"chart_modules");
|
||||||
|
my $mWorld = drawRegionsMap("locations","countryname","world","map_world");
|
||||||
|
my $mEU = drawRegionsMap("locations","countryname","150","map_europe");
|
||||||
|
my $mWesternEU = drawMarkersMap("locations","city","155","map_germany");
|
||||||
|
my $tModules = drawTable3cols("modules","total_modules","string","Module","number","Used","number","Definitions","table_modules");
|
||||||
|
#my $tModDef = drawTable("modules","total_moddef","string","Module","number","Definitions","table_moddef");
|
||||||
|
my $tModels = drawTable2cols("models","total_models","string","Model","boolean","defined","table_models");
|
||||||
|
my @res = $dbh->selectrow_array("SELECT created FROM db");
|
||||||
|
my $since = "@res";
|
||||||
|
|
||||||
|
print header;
|
||||||
|
print start_html(
|
||||||
|
-title => 'fhem.de - Statistics',
|
||||||
|
-author => 'm_fischer@gmx.de',
|
||||||
|
-base => 'true',
|
||||||
|
-style => {-src => $css},
|
||||||
|
-meta => {'keywords' => 'fhem houseautomation statistics'},
|
||||||
|
-script => [
|
||||||
|
{ -type => 'text/javascript',
|
||||||
|
-src => 'https://www.google.com/jsapi',
|
||||||
|
},
|
||||||
|
$visLib,
|
||||||
|
$cOS, $cArch, $cRelease, $cPerl,
|
||||||
|
# $cModulesTop10, $cModDefTop10,
|
||||||
|
$cModules,
|
||||||
|
$mWorld, $mEU, $mWesternEU,
|
||||||
|
$tModules, $tModels,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
my ($nodes) = $dbh->selectrow_array("SELECT COUNT(uniqueID) FROM nodes");
|
||||||
|
|
||||||
|
print <<END;
|
||||||
|
<div id="logo"></div>
|
||||||
|
<div id="menu">
|
||||||
|
<table><tbody><tr><td>
|
||||||
|
<table id="room">
|
||||||
|
<tr><td></td></tr>
|
||||||
|
<tr><td><b>back to</b></td></tr>
|
||||||
|
<tr><td></td></tr>
|
||||||
|
<tr><td><a href="http://fhem.de">Homepage</a></td></tr>
|
||||||
|
<tr><td></td></tr>
|
||||||
|
</tbody></table>
|
||||||
|
</td></tr></tbody></table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="right">
|
||||||
|
<noscript>
|
||||||
|
<div style="text-align:center; border: 2px solid red; background: #D7FFFF;">
|
||||||
|
<div style="text-align:center; background: #D7FFFF; color: red;">
|
||||||
|
<h4>Please enable Javascript on your Browser!</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</noscript>
|
||||||
|
|
||||||
|
<h3>Fhem Statistics ($nodes submissions since $since)</h3>
|
||||||
|
<h4>Installed on...</h4>
|
||||||
|
<div id="chart_os" style="float:left; border: 1px solid black; margin-right:25px;"></div>
|
||||||
|
<div id="chart_arch" style="float:left; border: 1px solid black;"></div>
|
||||||
|
<div style="clear:both;"></div>
|
||||||
|
|
||||||
|
<h4>Versions...</h4>
|
||||||
|
<div id="chart_release" style="float:left; border: 1px solid black; margin-right:25px;"></div>
|
||||||
|
<div id="chart_perl" style="float:left; border: 1px solid black;"></div>
|
||||||
|
<div style="clear:both;"></div>
|
||||||
|
|
||||||
|
<!-- graphs disabled
|
||||||
|
// <h4>Top 10 of most commonly used modules<small><sup>1</sup></small>...</h4>
|
||||||
|
// <div id="chart_modulestop10" style="width: 825px; height: 300px; border: 1px solid black;"></div>
|
||||||
|
// <small><sup>1</sup> excluded from graph: $excludeFromTop10modules</small>
|
||||||
|
//
|
||||||
|
// <h4>Top 10 of total definitions by module<small><sup>1</sup></small>...</h4>
|
||||||
|
// <div id="chart_moddeftop10" style="width: 825px; height: 300px; border: 1px solid black;"></div>
|
||||||
|
// <small><sup>1</sup> excluded from graph: $excludeFromTop10definitions</small>
|
||||||
|
//-->
|
||||||
|
<h4>Top 20 of most commonly used modules (with total definitions by module)...</h4>
|
||||||
|
<div id="chart_modules" style="width: 825px; height: 600px; border: 1px solid black;"></div>
|
||||||
|
|
||||||
|
<h4>Locations worldwide...</h4>
|
||||||
|
<div id="map_world" style="width: 825px; height: 500px; border: 1px solid black;"></div>
|
||||||
|
|
||||||
|
<h4>Locations in Europe...</h4>
|
||||||
|
<div id="map_europe" style="width: 825px; height: 500px; border: 1px solid black;"></div>
|
||||||
|
|
||||||
|
<h4>Locations in Western Europe...</h4>
|
||||||
|
<div id="map_germany" style="width: 825px; height: 500px; border: 1px solid black;"></div>
|
||||||
|
|
||||||
|
<div style="float:left; width: 400px; margin-right:25px;">
|
||||||
|
<h4>List of total used modules (with definitions)...</h4>
|
||||||
|
<div id="table_modules" style="width: 400px; border: 1px solid black;"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="float:left; width: 400px;">
|
||||||
|
<h4>List of defined models...</h4>
|
||||||
|
<div id="table_models" style="width: 400px; border: 1px solid black;"></div>
|
||||||
|
</div>
|
||||||
|
<div style="clear:both;"></div>
|
||||||
|
|
||||||
|
<div id="footer" style="position:relative; left: -100px; text-align: center;">
|
||||||
|
<p><small>Layout by M. Fischer - Click <a href="http://www.fischer-net.de/kontakt.html">here</a> to leave your comments.</small></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
END
|
||||||
|
print end_html;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub googleVisualizationLib($) {
|
||||||
|
my $packages = shift;
|
||||||
|
my $code =<<END;
|
||||||
|
// Load the Visualization API library
|
||||||
|
google.load('visualization', '1.0', {'packages':[$packages]});
|
||||||
|
END
|
||||||
|
return $code;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub drawPieChart(@) {
|
||||||
|
my ($table,$column,$title,$width,$height,$divID) = @_;
|
||||||
|
my $res = $dbh->selectall_arrayref("SELECT DISTINCT $column FROM $table ORDER BY $column ASC");
|
||||||
|
|
||||||
|
my %hash = ();
|
||||||
|
foreach my $row (@$res) {
|
||||||
|
my ($value) = @$row;
|
||||||
|
my ($count) = $dbh->selectrow_array("SELECT COUNT(*) FROM $table WHERE $column = '$value'");
|
||||||
|
$hash{$value} = $count;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $addRows;
|
||||||
|
foreach my $value (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
|
||||||
|
$addRows .= "\t['$value',$hash{$value}],\n";
|
||||||
|
}
|
||||||
|
chop($addRows);
|
||||||
|
|
||||||
|
my $code =<<END;
|
||||||
|
google.setOnLoadCallback(drawChart_$column);
|
||||||
|
|
||||||
|
function drawChart_$column() {
|
||||||
|
var data = new google.visualization.DataTable();
|
||||||
|
data.addColumn('string', 'Topping');
|
||||||
|
data.addColumn('number', 'Slices');
|
||||||
|
data.addRows([
|
||||||
|
$addRows
|
||||||
|
]);
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
title : '$title',
|
||||||
|
width : $width,
|
||||||
|
height : $height,
|
||||||
|
is3D : true,
|
||||||
|
tooltip : { showColorCode: true, },
|
||||||
|
};
|
||||||
|
|
||||||
|
var chart = new google.visualization.PieChart(document.getElementById('$divID'));
|
||||||
|
chart.draw(data, options);
|
||||||
|
};
|
||||||
|
END
|
||||||
|
|
||||||
|
return $code;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub drawColumnChartTop10Modules(@) {
|
||||||
|
my ($table,$postfix,$rowtitle,$width,$height,$divID) = @_;
|
||||||
|
$sth = $dbh->prepare("SELECT * FROM $table where 1=0");
|
||||||
|
$sth->execute();
|
||||||
|
my $res = $sth->{NAME};
|
||||||
|
$sth->finish;
|
||||||
|
|
||||||
|
my %hash = ();
|
||||||
|
foreach my $column (@$res) {
|
||||||
|
#my ($sum) = $dbh->selectrow_array("SELECT sum($column) FROM $table");
|
||||||
|
my ($sum) = $dbh->selectrow_array("SELECT count('$column') FROM $table");
|
||||||
|
$hash{$column} = $sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $data;
|
||||||
|
my $i=0;
|
||||||
|
foreach my $column (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
|
||||||
|
next if($column eq "uniqueID");
|
||||||
|
next if($excludeFromTop10modules =~ /$column/);
|
||||||
|
$data .= "\t['$column',$hash{$column}],\n";
|
||||||
|
$i++;
|
||||||
|
last if($i == 10);
|
||||||
|
}
|
||||||
|
chop($data);
|
||||||
|
|
||||||
|
my $code =<<END;
|
||||||
|
google.setOnLoadCallback(drawChart_$postfix);
|
||||||
|
function drawChart_$postfix() {
|
||||||
|
var data = google.visualization.arrayToDataTable([
|
||||||
|
['Module','$rowtitle'],
|
||||||
|
$data
|
||||||
|
]);
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
// title : 'title',
|
||||||
|
};
|
||||||
|
|
||||||
|
var chart = new google.visualization.ColumnChart(document.getElementById('$divID'));
|
||||||
|
chart.draw(data, options);
|
||||||
|
};
|
||||||
|
END
|
||||||
|
return $code;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub drawColumnChartTop10ModDef(@) {
|
||||||
|
my ($table,$postfix,$rowtitle,$width,$height,$divID) = @_;
|
||||||
|
$sth = $dbh->prepare("SELECT * FROM $table where 1=0");
|
||||||
|
$sth->execute();
|
||||||
|
my $res = $sth->{NAME};
|
||||||
|
$sth->finish;
|
||||||
|
|
||||||
|
my %hash = ();
|
||||||
|
foreach my $column (@$res) {
|
||||||
|
my ($sum) = $dbh->selectrow_array("SELECT sum($column) FROM $table");
|
||||||
|
$hash{$column} = $sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $data;
|
||||||
|
my $i=0;
|
||||||
|
foreach my $column (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
|
||||||
|
next if($column eq "uniqueID");
|
||||||
|
next if($excludeFromTop10definitions =~ /$column/);
|
||||||
|
$data .= "\t['$column',$hash{$column}],\n";
|
||||||
|
$i++;
|
||||||
|
last if($i == 10);
|
||||||
|
}
|
||||||
|
chop($data);
|
||||||
|
|
||||||
|
my $code =<<END;
|
||||||
|
google.setOnLoadCallback(drawChart_$postfix);
|
||||||
|
function drawChart_$postfix() {
|
||||||
|
var data = google.visualization.arrayToDataTable([
|
||||||
|
['Module','$rowtitle'],
|
||||||
|
$data
|
||||||
|
]);
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
// title : 'title',
|
||||||
|
};
|
||||||
|
|
||||||
|
var chart = new google.visualization.ColumnChart(document.getElementById('$divID'));
|
||||||
|
chart.draw(data, options);
|
||||||
|
};
|
||||||
|
END
|
||||||
|
return $code;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub drawBarChartModules(@) {
|
||||||
|
my ($table,$postfix,$row1title,$row2title,$width,$height,$divID) = @_;
|
||||||
|
$sth = $dbh->prepare("SELECT * FROM $table where 1=0");
|
||||||
|
$sth->execute();
|
||||||
|
my $res = $sth->{NAME};
|
||||||
|
$sth->finish;
|
||||||
|
|
||||||
|
my %hash = ();
|
||||||
|
foreach my $column (@$res) {
|
||||||
|
my ($count) = $dbh->selectrow_array("SELECT count($column) FROM $table WHERE $column > 0");
|
||||||
|
my ($sum) = $dbh->selectrow_array("SELECT sum($column) FROM $table");
|
||||||
|
$hash{$column}{count} = $count;
|
||||||
|
$hash{$column}{sum} = $sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $data;
|
||||||
|
my $i=0;
|
||||||
|
foreach my $column (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
|
||||||
|
next if($column eq "uniqueID");
|
||||||
|
$data .= "\t['$column',$hash{$column}{count},$hash{$column}{sum}],\n";
|
||||||
|
$i++;
|
||||||
|
last if($i == 20);
|
||||||
|
}
|
||||||
|
chop($data);
|
||||||
|
|
||||||
|
my $code =<<END;
|
||||||
|
google.setOnLoadCallback(drawChart_$postfix);
|
||||||
|
function drawChart_$postfix() {
|
||||||
|
var data = google.visualization.arrayToDataTable([
|
||||||
|
['Module','$row1title','$row2title'],
|
||||||
|
$data
|
||||||
|
]);
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
height : $height,
|
||||||
|
width : $width,
|
||||||
|
chartArea : {left:150,top:20,width:"65%",height:"90%"},
|
||||||
|
// title : 'title',
|
||||||
|
};
|
||||||
|
|
||||||
|
var chart = new google.visualization.BarChart(document.getElementById('$divID'));
|
||||||
|
chart.draw(data, options);
|
||||||
|
};
|
||||||
|
END
|
||||||
|
return $code;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub drawMarkersMap(@) {
|
||||||
|
my ($table,$column,$region,$divID) = @_;
|
||||||
|
my $res = $dbh->selectall_arrayref("SELECT DISTINCT $column FROM $table ORDER BY $column ASC");
|
||||||
|
|
||||||
|
my %hash = ();
|
||||||
|
foreach my $row (@$res) {
|
||||||
|
my ($value) = @$row;
|
||||||
|
my ($count) = $dbh->selectrow_array("SELECT COUNT(*) FROM $table WHERE $column = '$value'");
|
||||||
|
#$value = "Germany" if($value eq "");
|
||||||
|
next if($value eq "");
|
||||||
|
$hash{$value} = $count;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $addRows;
|
||||||
|
foreach my $value (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
|
||||||
|
$addRows .= "\t['$value',$hash{$value}],\n";
|
||||||
|
}
|
||||||
|
chop($addRows);
|
||||||
|
|
||||||
|
my $code=<<END;
|
||||||
|
google.setOnLoadCallback(drawMarkersMap_$region);
|
||||||
|
|
||||||
|
function drawMarkersMap_$region() {
|
||||||
|
var data = google.visualization.arrayToDataTable([
|
||||||
|
['City','Installations'],
|
||||||
|
$addRows
|
||||||
|
]);
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
region: '$region',
|
||||||
|
displayMode: 'markers',
|
||||||
|
colorAxis: {colors: ['green', 'blue']}
|
||||||
|
};
|
||||||
|
|
||||||
|
var chart = new google.visualization.GeoChart(document.getElementById('$divID'));
|
||||||
|
chart.draw(data, options);
|
||||||
|
};
|
||||||
|
END
|
||||||
|
|
||||||
|
return $code;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub drawRegionsMap(@) {
|
||||||
|
my ($table,$column,$region,$divID) = @_;
|
||||||
|
my $res = $dbh->selectall_arrayref("SELECT DISTINCT $column FROM $table ORDER BY $column ASC");
|
||||||
|
|
||||||
|
my %hash = ();
|
||||||
|
foreach my $row (@$res) {
|
||||||
|
my ($value) = @$row;
|
||||||
|
my ($count) = $dbh->selectrow_array("SELECT COUNT(*) FROM $table WHERE $column = '$value'");
|
||||||
|
$hash{$value} = $count;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $addRows;
|
||||||
|
foreach my $value (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
|
||||||
|
$addRows .= "\t['$value',$hash{$value}],\n";
|
||||||
|
}
|
||||||
|
chop($addRows);
|
||||||
|
|
||||||
|
my $code=<<END;
|
||||||
|
google.setOnLoadCallback(drawRegionsMap_$region);
|
||||||
|
|
||||||
|
function drawRegionsMap_$region() {
|
||||||
|
var data = google.visualization.arrayToDataTable([
|
||||||
|
['Country','Installations'],
|
||||||
|
$addRows
|
||||||
|
]);
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
region: '$region',
|
||||||
|
};
|
||||||
|
|
||||||
|
var chart = new google.visualization.GeoChart(document.getElementById('$divID'));
|
||||||
|
chart.draw(data, options);
|
||||||
|
};
|
||||||
|
END
|
||||||
|
return $code;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub drawTable2cols(@) {
|
||||||
|
my ($table,$postfix,$type1,$title1,$type2,$title2,$divID) = @_;
|
||||||
|
$sth = $dbh->prepare("SELECT * FROM $table where 1=0");
|
||||||
|
$sth->execute();
|
||||||
|
my $res = $sth->{NAME};
|
||||||
|
$sth->finish;
|
||||||
|
|
||||||
|
my %hash = ();
|
||||||
|
foreach my $column (@$res) {
|
||||||
|
my ($sum) = $dbh->selectrow_array("SELECT sum(\"$column\") FROM $table");
|
||||||
|
$hash{$column} = $sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $data;
|
||||||
|
if($type2 eq "boolean") {
|
||||||
|
foreach my $column (sort keys %hash) {
|
||||||
|
next if($column eq "uniqueID");
|
||||||
|
$data .= "\t['$column',true],\n";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
foreach my $column (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
|
||||||
|
next if($column eq "uniqueID");
|
||||||
|
$data .= "\t['$column',$hash{$column}],\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chop($data);
|
||||||
|
|
||||||
|
my $code=<<END;
|
||||||
|
google.setOnLoadCallback(drawTable_$postfix);
|
||||||
|
function drawTable_$postfix() {
|
||||||
|
var data = new google.visualization.DataTable();
|
||||||
|
data.addColumn('$type1', '$title1');
|
||||||
|
data.addColumn('$type2', '$title2');
|
||||||
|
data.addRows([
|
||||||
|
$data
|
||||||
|
]);
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
showRowNumber : false,
|
||||||
|
sortAscending : true,
|
||||||
|
sortColumn : 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
var table = new google.visualization.Table(document.getElementById('$divID'));
|
||||||
|
table.draw(data,options);
|
||||||
|
};
|
||||||
|
END
|
||||||
|
return $code;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub drawTable3cols(@) {
|
||||||
|
my ($table,$postfix,$type1,$title1,$type2,$title2,$type3,$title3,$divID) = @_;
|
||||||
|
$sth = $dbh->prepare("SELECT * FROM $table where 1=0");
|
||||||
|
$sth->execute();
|
||||||
|
my $res = $sth->{NAME};
|
||||||
|
$sth->finish;
|
||||||
|
|
||||||
|
my %hash = ();
|
||||||
|
foreach my $column (@$res) {
|
||||||
|
my ($count) = $dbh->selectrow_array("SELECT count(\"$column\") FROM $table WHERE \"$column\" > 0");
|
||||||
|
my ($sum) = $dbh->selectrow_array("SELECT sum(\"$column\") FROM $table");
|
||||||
|
$hash{$column}{count} = $count;
|
||||||
|
$hash{$column}{sum} = $sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $data;
|
||||||
|
foreach my $column (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
|
||||||
|
next if($column eq "uniqueID");
|
||||||
|
$data .= "\t['$column',$hash{$column}{count},$hash{$column}{sum}],\n";
|
||||||
|
}
|
||||||
|
chop($data);
|
||||||
|
|
||||||
|
my $code=<<END;
|
||||||
|
google.setOnLoadCallback(drawTable_$postfix);
|
||||||
|
function drawTable_$postfix() {
|
||||||
|
var data = new google.visualization.DataTable();
|
||||||
|
data.addColumn('$type1', '$title1');
|
||||||
|
data.addColumn('$type2', '$title2');
|
||||||
|
data.addColumn('$type3', '$title3');
|
||||||
|
data.addRows([
|
||||||
|
$data
|
||||||
|
]);
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
showRowNumber : false,
|
||||||
|
sortAscending : true,
|
||||||
|
sortColumn : 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
var table = new google.visualization.Table(document.getElementById('$divID'));
|
||||||
|
table.draw(data,options);
|
||||||
|
};
|
||||||
|
END
|
||||||
|
return $code;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub createDB() {
|
||||||
|
my $dbh = DBI->connect($dsn,"","", { RaiseError => 1, ShowErrorStatement => 1 }) ||
|
||||||
|
die "Cannot connect: $DBI::errstr";
|
||||||
|
$dbh->do("CREATE TABLE db (created TIMESTAMP DEFAULT CURRENT_TIMESTAMP)");
|
||||||
|
$dbh->do("CREATE TABLE nodes (uniqueID VARCHAR(32) PRIMARY KEY UNIQUE, release VARCHAR(16), branch VARCHAR(32), os VARCHAR(32), arch VARCHAR(64), perl VARCHAR(16), lastSeen TIMESTAMP DEFAULT CURRENT_TIMESTAMP)");
|
||||||
|
$dbh->do("CREATE TABLE locations (uniqueID VARCHAR(32) PRIMARY KEY UNIQUE, countrycode VARCHAR(2), countrycode3 VARCHAR(3), countryname VARCHAR(64), region CHAR(2) ,regionname VARCHAR(64), city VARCHAR(255), latitude FLOAT(8,6), longitude FLOAT(8,6), timezone VARCHAR(64), continentcode CHAR(2))");
|
||||||
|
$dbh->do("CREATE TABLE modules (uniqueID VARCHAR(32) PRIMARY KEY UNIQUE)");
|
||||||
|
$dbh->do("CREATE TABLE models (uniqueID VARCHAR(32) PRIMARY KEY UNIQUE)");
|
||||||
|
$dbh->do("INSERT INTO db (created) VALUES (CURRENT_TIMESTAMP)");
|
||||||
|
$dbh->disconnect();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub insertDB() {
|
||||||
|
my $uniqueID = $data{uniqueID};
|
||||||
|
my $modules = $data{modules};
|
||||||
|
my $models = $data{models};
|
||||||
|
my $sth;
|
||||||
|
|
||||||
|
# insert or update fhem node
|
||||||
|
my ($release,$branch,$os,$arch,$perl);
|
||||||
|
foreach (split(/\|/,$data{system})) {
|
||||||
|
my ($k,$v) = split /:/;
|
||||||
|
$release = $v if($k eq "Release");
|
||||||
|
$branch = $v if($k eq "Branch");
|
||||||
|
$os = $v if($k eq "OS");
|
||||||
|
$arch = $v if($k eq "Arch");
|
||||||
|
$perl = $v if($k eq "Perl");
|
||||||
|
}
|
||||||
|
$sth = $dbh->prepare(q{REPLACE INTO nodes (uniqueID,release,branch,os,arch,perl,lastSeen) VALUES(?,?,?,?,?,?,CURRENT_TIMESTAMP)});
|
||||||
|
$sth->execute($uniqueID,$release,$branch,$os,$arch,$perl);
|
||||||
|
|
||||||
|
# insert or update goe location of fhem node
|
||||||
|
#### TODO: sprachcode 84.191.75.195
|
||||||
|
my @geo = getLocation($ip);
|
||||||
|
|
||||||
|
if(@geo) {
|
||||||
|
$sth = $dbh->prepare(q{REPLACE INTO locations (uniqueID,countrycode,countrycode3,countryname,region,regionname,city,latitude,longitude,timezone,continentcode) VALUES(?,?,?,?,?,?,?,?,?,?,?)});
|
||||||
|
$sth->execute($uniqueID,$geo[0],$geo[1],$geo[2],$geo[3],$geo[4],$geo[5],$geo[6],$geo[7],$geo[8],$geo[9]);
|
||||||
|
}
|
||||||
|
|
||||||
|
# delete old modules of fhem node
|
||||||
|
$sth = $dbh->prepare(q{DELETE FROM modules WHERE uniqueID=?});
|
||||||
|
$sth->execute($uniqueID);
|
||||||
|
|
||||||
|
# insert new modules of fhem node
|
||||||
|
$sth = $dbh->prepare("INSERT INTO modules (uniqueID) VALUES (?)");
|
||||||
|
$sth->execute($uniqueID);
|
||||||
|
|
||||||
|
foreach (split(/\|/,$data{modules})) {
|
||||||
|
my ($k,$v) = split /:/;
|
||||||
|
checkColumn("modules",$k);
|
||||||
|
|
||||||
|
$sth = $dbh->prepare("UPDATE modules SET '$k'='$v' WHERE uniqueID='$uniqueID'");
|
||||||
|
$sth->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
if($data{models}) {
|
||||||
|
# delete old models of fhem node
|
||||||
|
$sth = $dbh->prepare(q{DELETE FROM models WHERE uniqueID=?});
|
||||||
|
$sth->execute($uniqueID);
|
||||||
|
|
||||||
|
# insert new modules of fhem node
|
||||||
|
$sth = $dbh->prepare("INSERT INTO models (uniqueID) VALUES (?)");
|
||||||
|
$sth->execute($uniqueID);
|
||||||
|
|
||||||
|
foreach (split(/\|/,$data{models})) {
|
||||||
|
my @models = split /,/;
|
||||||
|
foreach my $m (@models) {
|
||||||
|
checkColumn("models",$m);
|
||||||
|
$sth = $dbh->prepare("UPDATE models SET '$m'='1' WHERE uniqueID='$uniqueID'");
|
||||||
|
$sth->execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$sth->finish();
|
||||||
|
$dbh->disconnect();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub checkColumn($$) {
|
||||||
|
my ($t,$k) = @_;
|
||||||
|
|
||||||
|
# get table info
|
||||||
|
$sth = $dbh->prepare("PRAGMA table_info($t)");
|
||||||
|
$sth->execute();
|
||||||
|
|
||||||
|
# check if column exists
|
||||||
|
my @row;
|
||||||
|
my @match = ();
|
||||||
|
while (@row = $sth->fetchrow_array()) {
|
||||||
|
@match = grep { /\b$k\b/ } @row;
|
||||||
|
last if(@match != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
# create column if not exists
|
||||||
|
if(@match == 0) {
|
||||||
|
$sth = $dbh->prepare("ALTER TABLE $t ADD COLUMN '$k' INTEGER DEFAULT 0");
|
||||||
|
$sth->execute();
|
||||||
|
}
|
||||||
|
$sth->finish;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub getLocation($) {
|
||||||
|
my ($ip) = shift;
|
||||||
|
my $gi = Geo::IP->open($geoIPDat, GEOIP_STANDARD);
|
||||||
|
my $rec = $gi->record_by_addr($ip);
|
||||||
|
|
||||||
|
if(!$rec) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
$rec->country_code,$rec->country_code3,$rec->country_name,$rec->region,$rec->region_name,$rec->city,
|
||||||
|
$rec->latitude,$rec->longitude,$rec->time_zone,$rec->continent_code
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
Loading…
x
Reference in New Issue
Block a user