mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-03-12 16:46:35 +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
@ -25,8 +25,6 @@ package main;
|
||||
use strict;
|
||||
use warnings;
|
||||
use Config;
|
||||
use HTTP::Request::Common qw(POST);
|
||||
use LWP::UserAgent;
|
||||
|
||||
sub CommandFheminfo($$);
|
||||
|
||||
@ -57,6 +55,21 @@ CommandFheminfo($$)
|
||||
my $name = "fheminfo";
|
||||
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");
|
||||
|
||||
my $branch = $DISTRIB_BRANCH;
|
||||
@ -125,7 +138,7 @@ CommandFheminfo($$)
|
||||
$ret = $str;
|
||||
|
||||
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);
|
||||
$req->content_type("application/x-www-form-urlencoded");
|
||||
my $contInfo;
|
||||
@ -200,6 +213,17 @@ sub checkConfigFile($) {
|
||||
|
||||
}
|
||||
|
||||
sub checkModule($) {
|
||||
my $module = shift;
|
||||
eval("use $module");
|
||||
|
||||
if($@) {
|
||||
return(0);
|
||||
} else {
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=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