=for comment # $Id$ This script is 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. =cut package main; use strict; use warnings; use HttpUtils; my $c_system = 'system'; my $c_noModel = 'noModel'; my %fhemInfo = (); my @ignoreList = qw(Global); my @noModelList = qw(readingsgroup lacrosse zwdongle wol weekdaytimer cul_rfr solarview lw12 tscul dummy at archetype pushover twilight notify cloneDummy structure FHEMWEB hminfo); sub fheminfo_Initialize { my %hash = ( Fn => "CommandFheminfo", Hlp => "[send],show or send Fhem statistics", uri => "https://fhem.de/stats/statistics2.cgi", ); $cmds{fheminfo} = \%hash; } sub CommandFheminfo { my ($cl,$param) = @_; my @args = split("[ \t]+", $param); $args[0] = defined($args[0]) ? lc($args[0]) : ""; my $doSend = ($args[0] eq 'send') ? 1 : 0; return "Unknown argument $args[0], usage: fheminfo [send]" if($args[0] ne "send" && $args[0] ne ""); return "Won't send, as sendStatistics is set to 'never'." if($doSend && lc(AttrVal("global","sendStatistics","")) eq "never"); _fi2_Count(); if (defined($args[1]) && $args[1] eq 'debug') { $fhemInfo{$c_system}{'uniqueID'} = _fi2_shortId(); return toJSON(\%fhemInfo); } _fi2_Send($cl) if $doSend; # do not return statistics data if called from update return "Statistics data sent to server. See Logfile (level 4) for details." unless defined($cl); return _fi2_TelnetTable($doSend) if ($cl && $cl->{TYPE} eq 'telnet'); return _fi2_HtmlTable($doSend); } ################################################################ # tools # sub _fi2_Count { my $uniqueID = getUniqueId(); my $os = $^O; my $perl = sprintf("%vd", $^V); %fhemInfo = (); $fhemInfo{$c_system}{'uniqueID'} = $uniqueID; $fhemInfo{$c_system}{'os'} = $os; $fhemInfo{$c_system}{'perl'} = $perl; $fhemInfo{$c_system}{'revision'} = _fi2_findRev(); $fhemInfo{$c_system}{'configType'} = configDBUsed() ? 'configDB' : 'configFile'; foreach my $key ( keys %defs ) { # 1. skip if device is TEMPORARY or VOLATILE next if (defined($defs{$key}{'TEMPORARY'}) || defined($defs{$key}{'VOLATILE'})); my $name = $defs{$key}{NAME}; my $type = $defs{$key}{TYPE}; my $model = $c_noModel; # 2. look for model information in internals $model = defined($defs{$key}{model}) ? $defs{$key}{model} : $model; $model = defined($defs{$key}{MODEL}) ? $defs{$key}{MODEL} : $model; if ($model eq $c_noModel) { # 3. look for model information in attributes $model = AttrVal($name,'model',$model); # 4. look for model information in readings $model = ReadingsVal($name,'model',$model); # special reading for BOSEST $model = ReadingsVal($name,'type',$model) if (lc($type) eq 'bosest'); # special reading for ZWave if (lc($type) eq 'zwave') { $model = ReadingsVal($name,'modelId',undef); next unless (defined($model)); next if ($model =~ /^0x.... /); $model = _fi2_zwave($model); } } # 5. ignore model for some modules foreach my $i (@noModelList) { $model = $c_noModel if (lc($type) eq $i); } # 6. protect against very old KNX modules $model = $c_noModel if ( lc($type) eq 'knx' && $model !~ /^dpt[\d]+/x); # 7. check if model is a scalar $model = $c_noModel if (ref($model) eq 'HASH'); # 8. skip for some special cases found in database next if ( ($model =~ /^unkno.*/i) || ($model =~ /virtual.*/i) || ($model =~ m/\berror\b/i) || ($model =~ m/^<.*>$/) || ($model eq '?') || ($model eq '1') || # (length($model) > 80) || (defined($defs{$key}{'chanNo'})) || ($name =~ m/^unknown_/) ); # 9. finally count it :) $fhemInfo{$type}{$model}++ ; } # now do some more special handlings # add model info for configDB if used eval { $fhemInfo{'configDB'}{_cfgDB_type()}++ if configDBUsed(); }; # delete all modules listed in ignoreList foreach my $i (@ignoreList) { delete $fhemInfo{$i}; } return; } sub _fi2_Send { my ($cl) = shift; $cl //= undef; my $sendType = defined($cl) ? 'nonblocking' : 'blocking'; my $json = toJSON(\%fhemInfo); Log3("fheminfo",4,"fheminfo send ($sendType): $json"); my %hu_hash = (); $hu_hash{url} = $cmds{fheminfo}{uri}; $hu_hash{data} = "uniqueID=".$fhemInfo{$c_system}{'uniqueID'}."&json=$json"; $hu_hash{header} = "User-Agent: FHEM"; if (defined($cl)) { $hu_hash{callback} = sub($$$) { my ($hash, $err, $data) = @_; if($err) { Log 1, "fheminfo send: Server ERROR: $err"; } else { Log3("fheminfo",4,"fheminfo send: Server RESPONSE: $data"); } }; HttpUtils_NonblockingGet(\%hu_hash); } else { my ($err, $data) = HttpUtils_BlockingGet(\%hu_hash); if($err) { Log 1, "fheminfo send: Server ERROR: $err"; } else { Log3("fheminfo",4,"fheminfo send: Server RESPONSE: $data"); } } return; } sub _fi2_TelnetTable { my ($doSend) = shift; my $str; $str .= "Following statistics data will be sent to server:\n(see Logfile level 4 for server response)\n\n" if($doSend == 1); $str .= "System Info\n"; $str .= sprintf(" ConfigType%*s: %s\n",3," ",$fhemInfo{$c_system}{'configType'}); $str .= sprintf(" SVN revision%*s: %s\n",0," ",$fhemInfo{$c_system}{'revision'}) if (defined($fhemInfo{$c_system}{'revision'})); $str .= sprintf(" OS%*s: %s\n",11," ",$fhemInfo{$c_system}{'os'}); $str .= sprintf(" Perl%*s: %s\n",9," ",$fhemInfo{$c_system}{'perl'}); $str .= sprintf(" uniqueID%*s: %s\n",5," ",_fi2_shortId()); my @keys = keys %fhemInfo; foreach my $type (sort @keys) { next if $type eq $c_system; $str .= "\nType: $type "; $str .= "Count: ".$fhemInfo{$type}{$c_noModel} if defined $fhemInfo{$type}{$c_noModel}; $str .= "\n"; while ( my ($model, $count) = each(%{$fhemInfo{$type}}) ) { $str .= " $model = $fhemInfo{$type}{$model}\n" unless $model eq $c_noModel; } } return $str; } sub _fi2_HtmlTable { my ($doSend) = shift; my $result = "
Following statistics data will be sent to server:(see Logfile level 4 for server response) | ||
System Info | ||
ConfigType: | $fhemInfo{$c_system}{'configType'} | |
SVN rev: | $fhemInfo{$c_system}{'revision'} | |
OS: | $fhemInfo{$c_system}{'os'} | |
Perl: | $fhemInfo{$c_system}{'perl'} | |
uniqueId: | "._fi2_shortId()." | |
Modules | Model | Count |
$type | $fhemInfo{$type}{$c_noModel} | |
$model | $fhemInfo{$type}{$model} |
fheminfo [send]
send
transmitts the collected data
to a central server in order to support the development of FHEM. send
parameter. They are set on attr global
.
update
command.
onUpdate
: transfer of data on every update (recommended setting).
manually
: manually transfer of data via the fheminfo send
command.
never
: prevents transmission of data at anytime.