diff --git a/fhem/FHEM/98_notice.pm b/fhem/FHEM/98_notice.pm new file mode 100644 index 000000000..ead6e341f --- /dev/null +++ b/fhem/FHEM/98_notice.pm @@ -0,0 +1,749 @@ +# $Id$ +# vim: ts=2:et +################################################################ +# +# Copyright notice +# +# (c) 2013 Copyright: Martin Fischer (m_fischer at gmx dot de) +# All rights reserved +# +# This file is part of fhem. +# +# Fhem 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 +# (at your option) any later version. +# +# Fhem is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with fhem. If not, see . +# +################################################################ + +package main; +use strict; +use warnings; +use Time::Local; + +sub CommandNotice($$); +sub notice_Confirmation($$$); +sub notice_Get($$$); +sub notice_List($$); +sub notice_Read($$$); + +use vars qw(@locale); +@locale = qw(de en); + +my $confirmationFile = ".notice-confirmation"; + +######################################## +sub +notice_Initialize($$) +{ + my %hash = ( + Fn => "CommandNotice", + Hlp => "[confirm|list|reset|view] ,view and confirmation of system messages", + ); + $cmds{notice} = \%hash; +} + +######################################## +sub +CommandNotice($$) +{ + my ($cl,$param) = @_; + my $modPath = (-d "updatefhem.dir" ? "updatefhem.dir":$attr{global}{modpath}); + my $modDir = "$modPath/FHEM"; + my $noticeDir = "$modDir/FhemUtils"; + my $name = "notice"; + my @commands = qw(confirm condition get list position reset view); + my $ret; + + # split arguments + my @args = split(/ +/,$param); + + $args[0] = "list" if(!defined($args[0])); + + if(!@args || $args[0] ~~ @commands) { + my $cmd = $args[0]; + + if($cmd eq "list") { + # view all a list of notes + my $type = "all"; + if(defined($args[1])) { + $type = $args[1]; + } + $ret = notice_List($noticeDir,$type); + + } elsif($cmd eq "view") { + # view a single note + return "notice view needs an argument" + if(!defined($args[1])); + + my $id = $args[1]; + my $notice_ref = {}; + $notice_ref = notice_Read($notice_ref,$noticeDir,$args[1]); + return "Nothing to view. Maybe wrong ID?" + if(!keys %$notice_ref); + + my $locale = "en"; + my $header = 1; + if(@args == 3) { + $locale = ($args[2] ~~ @locale) ? $args[2] : "en"; + $header = ($args[2] eq "noheader") ? 0 : 1; + } elsif(@args == 4) { + if($args[2] ~~ @locale) { + $locale = ($args[2] ~~ @locale) ? $args[2] : "en"; + $header = ($args[3] eq "noheader") ? 0 : 1; + } elsif($args[2] eq "noheader") { + $header = ($args[2] eq "noheader") ? 0 : 1; + $locale = ($args[3] ~~ @locale) ? $args[3] : "en"; + } + } + + if($header) { + $ret = sprintf("%-10s: %s\n","ID",$id); + $ret .= sprintf("%-10s: %s\n","From",$notice_ref->{$id}{from}) + if(exists $notice_ref->{$id}{from}); + $ret .= sprintf("%-10s: %s\n","Date",$notice_ref->{$id}{date}) + if(exists $notice_ref->{$id}{from}); + $ret .= sprintf("%-10s: %s\n","Expire",$notice_ref->{$id}{expire}) + if(exists $notice_ref->{$id}{expire}); + $ret .= sprintf("%-10s: %s\n","Title",$notice_ref->{$id}{locale}{$locale}{title}) + if(exists $notice_ref->{$id}{locale}{$locale}{title}); + $ret .= "### Start of Text\n"; + } + + foreach my $line (@{$notice_ref->{$id}{locale}{$locale}{text}}) { + $ret .= $line."\n"; + } + + $ret .= "### End of Text\n" if($header); + + } elsif($cmd eq "confirm") { + # confirm a note + return "notice view needs an argument" + if(!defined($args[1])); + + my $id = $args[1]; + my $notice_ref = {}; + $notice_ref = notice_Read($notice_ref,$noticeDir,$id); + return "Nothing to view. Maybe wrong ID?" + if(!keys %$notice_ref); + + if(!defined($notice_ref->{$id}{confirm}) || + (defined($notice_ref->{$id}{confirm}) && $notice_ref->{$id}{confirm} == 0) ) { + return "$id needs no confirmation."; + } else { + my $confirmation = 1; + if(@args > 2) { + shift @args; + shift @args; + $confirmation = "@args"; + } + $ret = notice_Confirmation($noticeDir,$id,$confirmation); + } + + } elsif($cmd eq "get") { + # get list of notes + my $type = (defined($args[1])) ? $args[1] : "all"; + my $value = (defined($args[2]) && $args[2] =~ /[0-8]/) ? $args[2] : 0; + return notice_Get($noticeDir,$type,$value); + + } elsif($cmd eq "position") { + # returns position of notice + return "notice position needs an argument" + if(!defined($args[1])); + + my $id = $args[1]; + my $notice_ref = {}; + $notice_ref = notice_Read($notice_ref,$noticeDir,$id); + return (defined($notice_ref->{$id}{position})) ? $notice_ref->{$id}{position} : undef; + } elsif($cmd eq "reset") { + # reset all confirmations + if(-e "$noticeDir/$confirmationFile") { + if(defined($args[1] && lc($args[1]) eq "yes")) { + my $cmdret = unlink "$noticeDir/$confirmationFile"; + if(!$cmdret) { + $ret = "an error occured while deleting file '$noticeDir/$confirmationFile': $!"; + } else { + $ret = "all confirmations deleted successfully."; + } + } else { + $ret = "This command delete all confirmations.\n"; + $ret .= "If you really want to do this, call 'notice reset yes'"; + return $ret; + } + } else { + $ret = "nothing to do. no confirmation exists."; + } + } elsif($cmd eq "condition") { + # supplies a value of an embedded test + return "condition view needs an argument" + if(!defined($args[1])); + + my $id = $args[1]; + my $notice_ref = {}; + $notice_ref = notice_Read($notice_ref,$noticeDir,$id); + return "Nothing to view. Maybe wrong ID?" + if(!keys %$notice_ref); + + my %conditions; + foreach my $key (sort %{$notice_ref->{$id}}) { + my $order; + if(lc($key) =~ /^key_/) { + (undef,$order) = split("_",$key); + if(defined($notice_ref->{$id}{"val_$order"})) { + $conditions{$notice_ref->{$id}{$key}}{value} = ($notice_ref->{$id}{"val_$order"}) ? + eval $notice_ref->{$id}{"val_$order"} : undef; + $conditions{$notice_ref->{$id}{$key}}{condition} = (defined($notice_ref->{$id}{"con_$order"})) ? + $notice_ref->{$id}{"con_$order"} : ""; + Log 5, "notice id:$id condition key:".$notice_ref->{$id}{$key} . " " . + "value:" .$conditions{$notice_ref->{$id}{$key}}{value} . " " . + "condition:".$notice_ref->{$id}{"val_$order"}; + } + } + } + + if(keys %conditions) { + foreach my $key (sort keys %conditions) { + Log 5, "notice id:$id condition key:$key value:$conditions{$key}{value} condition:$conditions{$key}{condition}"; + $ret .= "$key:$conditions{$key}{value}:$conditions{$key}{condition}"; + $ret .= "|"; + } + chop $ret; + return $ret; + } else { + return undef; + } + + } + + + } else { + return "Unknown argument $args[0]; choose one of " . join(" ", sort @commands); + } + + return $ret; +} + +######################################## +sub +notice_List($$) +{ + my ($noticeDir,$type) = @_; + $type = ($type eq "all") ? ".*" : $type; + my @dir; + my $ret; + + if(opendir(my $DH, "$noticeDir")) { + @dir = grep { /^$type-.*\d+$/ && -f "$noticeDir/$_" } readdir($DH); + closedir $DH; + + my $notice_ref = {}; + foreach my $file (@dir) { + $notice_ref = notice_Read($notice_ref,$noticeDir,$file); + } + + my @col1 = sort keys %{$notice_ref}; + my $col1 = (reverse sort { $a <=> $b } map { length($_) } @col1)[0]; + if(!keys %$notice_ref) { + $ret = "==> nothing found"; + } else { + + my @confirmationFile; + if(open(my $FH, "<$noticeDir/$confirmationFile")) { + Log 5, "notice read file: $noticeDir/$confirmationFile"; + while(my $line = <$FH>) { + chomp $line; + push(@confirmationFile,$line); + } + close $FH; + } + + foreach my $lang (sort @locale) { + $ret .= "==> Language: $lang\n"; + $ret .= sprintf(" %-*s %-10s %-10s %-10s %s\n",$col1,"ID","Published","Expired","Confirmed","Description"); + foreach my $notice (sort keys %{$notice_ref}) { + my ($dateTime,$oldConfirmation); + next if(!exists $notice_ref->{$notice}{locale}{$lang}); + foreach my $line (@confirmationFile) { + if($line =~ /^$notice\s*/) { + ($dateTime,$oldConfirmation) = $line =~ /^.*\s*(\d{4}-\d{2}-\d{2})\s\d{2}:\d{2}:\d{2}\s*(.*)$/; + $dateTime = substr($dateTime,8,2).".".substr($dateTime,5,2).".".substr($dateTime,0,4); + } + } + $ret .= sprintf(" %-*s %-10s %-10s %-10s %s\n", + $col1, + $notice, + (defined($notice_ref->{$notice}{publish}) && $notice_ref->{$notice}{publish} ne "0") ? + $notice_ref->{$notice}{publish} : "actually", + (defined($notice_ref->{$notice}{expire}) && $notice_ref->{$notice}{expire} ne "0") ? + $notice_ref->{$notice}{expire} : "never", + ($dateTime) ? $dateTime : + (defined($notice_ref->{$notice}{confirm}) && $notice_ref->{$notice}{confirm} ne "0") ? + "no" : "not needed", + $notice_ref->{$notice}{locale}{$lang}{title}); + } + $ret .= "\n"; + } + chomp $ret; + } + + } else { + $ret = "update could not open directory '$noticeDir': $!"; + Log 1, $ret; + } + + return $ret; +} + +######################################## +# value: 0 = all +# 1 = not confirmed +# 2 = not expired +# 3 = not confirmed, not expired +# 4 = published +# 5 = not confirmed, published +# 6 = not expired, published +# 7 = not confirmed, not expired, published +# 8 = confirmed +sub +notice_Get($$$) +{ + my ($noticeDir,$type,$value) = @_; + $value = ($value) ? $value : 0; + my @now = localtime(); + + my @dir; + + if(opendir(my $DH, "$noticeDir")) { + my $search = ($type eq "all") ? ".*" : $type; + @dir = grep { /^$search-.*\d+$/ && -f "$noticeDir/$_" } readdir($DH); + closedir $DH; + } else { + Log 1, "notice could not open directory '$noticeDir': $!"; + } + + my @confirmed; + if($value == 1 || $value == 3 || $value == 5 || $value == 7 || $value == 8) { + if(open(my $FH, "<$noticeDir/$confirmationFile")) { + Log 5, "notice read file: $noticeDir/$confirmationFile"; + while(my $line = <$FH>) { + my ($id,undef) = split(" ",$line); + if($type eq "all") { + push(@confirmed,$id); + } elsif($id =~ /^$type/) { + push(@confirmed,$id); + } + } + close $FH; + } + } + + if(@dir) { + my $notice_ref = {}; + foreach my $file (sort @dir) { + $notice_ref = notice_Read($notice_ref,$noticeDir,$file); + } + + if(!keys %$notice_ref) { + return undef; + } else { + + my $ret; + if($value == 0) { + # all + $ret = join(",",sort @dir); + } elsif($value == 1) { + # not confirmed + $ret = _notConfirmed($notice_ref,@confirmed); + Log 5, "notice notConfirmed:$ret"; + } elsif($value == 2) { + # not expired + $ret = _notExpired($notice_ref,@now); + Log 5, "notice notExpired:$ret"; + } elsif($value == 3) { + # not confirmed, not expired + my $notConfirmed = _notConfirmed($notice_ref,@confirmed); + my $notExpired = _notExpired($notice_ref,@now); + Log 5, "notice notConfirmed:$notConfirmed notExpired:$notExpired"; + my @merged; + foreach my $id (@dir) { + push (@merged, $id) if($notConfirmed =~ /$id/ && $notExpired =~ /$id/); + } + $ret = join(",",sort @merged); + } elsif($value == 4) { + # published + $ret = _published($notice_ref,@now); + Log 5, "notice published:$ret"; + } elsif($value == 5) { + # not confirmed, published + my $notConfirmed = _notConfirmed($notice_ref,@confirmed); + my $published = _published($notice_ref,@now); + Log 5, "notice notConfirmed:$notConfirmed published:$published"; + my @merged; + foreach my $id (sort @dir) { + push (@merged, $id) if($notConfirmed =~ /$id/ && $published =~ /$id/); + } + $ret = join(",",sort @merged); + } elsif($value == 6) { + # not expired, published + my $notExpired = _notExpired($notice_ref,@now); + my $published = _published($notice_ref,@now); + Log 5, "notice notExpired:$notExpired published:$published"; + my @merged; + foreach my $id (sort @dir) { + push (@merged, $id) if($notExpired =~ /$id/ && $published =~ /$id/); + } + $ret = join(",",sort @merged); + } elsif($value == 7) { + # not confirmed, not expired, published + my $notConfirmed = _notConfirmed($notice_ref,@confirmed); + my $notExpired = _notExpired($notice_ref,@now); + my $published = _published($notice_ref,@now); + Log 5, "notice notConfirmed:$notConfirmed notExpired:$notExpired published:$published"; + my @merged; + foreach my $id (sort @dir) { + push (@merged, $id) if($notConfirmed =~ /$id/ && $notExpired =~ /$id/ && $published =~ /$id/); + } + $ret = join(",",sort @merged); + } elsif($value == 8) { + # confirmed + $ret = join(",",sort @confirmed); + } + + return $ret; + + } + + } else { + return undef; + } + +} + +######################################## +sub +_notConfirmed($@) +{ + my ($notice_ref,@confirmed) = @_; + my @ret; + foreach my $id (sort keys %{$notice_ref}) { + push(@ret,$id) + if(defined($notice_ref->{$id}{confirm}) && + $notice_ref->{$id}{confirm} != 0 && !grep (m/^$id$/,@confirmed)); + } + return join(",",@ret); +} + +######################################## +sub +_notExpired($@) +{ + my ($notice_ref,@now) = @_; + my @ret; + foreach my $id (sort keys %{$notice_ref}) { + my ($d,$m,$y); + if(defined($notice_ref->{$id}{expire}) && $notice_ref->{$id}{expire} =~ /\d{2}.\d{2}.\d{4}/) { + $d = substr($notice_ref->{$id}{expire},0,2); + $m = substr($notice_ref->{$id}{expire},3,2)-1; + $y = substr($notice_ref->{$id}{expire},6,4)-1900; + } + push(@ret,$id) + if(!defined($notice_ref->{$id}{expire}) || + (defined($notice_ref->{$id}{expire}) && $notice_ref->{$id}{expire} !~ /\d{2}.\d{2}.\d{4}/) || + (defined($notice_ref->{$id}{expire}) && $notice_ref->{$id}{expire} =~ /\d{2}.\d{2}.\d{4}/ && + notice_epochDate($now[3],$now[4],$now[5]) <= notice_epochDate($d,$m,$y))); + } + return join(",",@ret); +} + +######################################## +sub +_published($@) +{ + my ($notice_ref,@now) = @_; + my @ret; + foreach my $id (sort keys %{$notice_ref}) { + my ($d,$m,$y); + if(defined($notice_ref->{$id}{publish}) && $notice_ref->{$id}{publish} =~ /\d{2}.\d{2}.\d{4}/) { + $d = substr($notice_ref->{$id}{publish},0,2); + $m = substr($notice_ref->{$id}{publish},3,2)-1; + $y = substr($notice_ref->{$id}{publish},6,4)-1900; + } + push(@ret,$id) + if(!defined($notice_ref->{$id}{publish}) || + (defined($notice_ref->{$id}{publish}) && $notice_ref->{$id}{publish} !~ /\d{2}.\d{2}.\d{4}/) || + (defined($notice_ref->{$id}{publish}) && $notice_ref->{$id}{publish} =~ /\d{2}.\d{2}.\d{4}/ && + notice_epochDate($now[3],$now[4],$now[5]) >= notice_epochDate($d,$m,$y))); + } + return join(",",@ret); +} + +######################################## +sub +notice_epochDate($$$) +{ + my ($day,$month,$year) = @_; + return timelocal("0","0","0",$day,$month,$year); +} + +######################################## +sub +notice_Confirmation($$$) +{ + my ($noticeDir,$id,$confirmation) = @_; + my @file; + my $confirmed = 0; + my $oldConfirmation; + my $dateTime; + my $now = TimeNow(); + my $ret; + + if(open(my $FH, "<$noticeDir/$confirmationFile")) { + Log 5, "notice read file: $noticeDir/$confirmationFile"; + while(my $line = <$FH>) { + chomp $line; + if($line =~ /^$id\s*/) { + ($dateTime,$oldConfirmation) = $line =~ /^.*\s*(\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2})\s*(.*)$/; + $confirmed = 1; + } + push(@file,$line); + } + close $FH; + } + + if($confirmed == 0) { + push(@file,"$id $now $confirmation\n"); + } + + if($oldConfirmation eq $confirmation) { + $ret = "$id already confirmed on $dateTime: $oldConfirmation"; + } else { + if(open(my $FH, ">$noticeDir/$confirmationFile")) { + Log 5, "notice write file: $noticeDir/$confirmationFile"; + foreach my $line (sort @file) { + if($line =~ /^$id\s*/) { + print $FH "$id $now $confirmation\n"; + if(!$oldConfirmation) { + $ret = "$id confirmed on $now: $confirmation"; + } else { + $ret = "$id changed on $now: $confirmation"; + } + Log 1, "notice $ret"; + } else { + print $FH "$line\n"; + } + } + } else { + $ret = "error while writing file: $noticeDir/$confirmationFile: $!"; + Log 1, "notice $ret"; + } + } + + return $ret; +} + +######################################## +sub +notice_Read($$$) +{ + my ($notice_ref,$noticeDir,$noticeFile) = @_; + my %notice = %$notice_ref if($notice_ref && ref($notice_ref) eq "HASH"); + + if(open(my $FH, "<$noticeDir/$noticeFile")) { + Log 5, "notice read file: $noticeDir/$noticeFile"; + my $key; + my $value; + my $locale; + while(my $line = <$FH>) { + chomp $line; + if(uc($line) =~ /^#\s.*:.*$/ && uc($line) !~ /^#\s*NOTICE_\S{2}$/ && uc($line) !~ /^#\s*TITLE_\S{2}\s*:.*$/) { + ($key,$value) = $line =~ /^#\s*(.*)\s*:\s*(.*)$/; + $notice{$noticeFile}{lc($key)} = $value; + } elsif (uc($line) =~ /^#\s*TITLE_\S{2}\s*:.*$/) { + ($locale,$value) = $line =~ /^#\s*TITLE_(\S{2})\s*:\s*(.*)$/; + $notice{$noticeFile}{locale}{lc($locale)}{title} = $value; + } elsif (uc($line) =~ /^#\s*NOTICE_\S{2}$/) { + ($locale) = $line =~ /^#\s*NOTICE_(\S{2})$/; + } else { + $locale = "EN" if(!$locale); + push @{ $notice{$noticeFile}{locale}{lc($locale)}{text} }, $line; + } + } + close $FH; + } else { + Log 1, "update could not open notice '$noticeDir/$noticeFile': $!"; + return undef; + } + return \%notice; +} + +=pod +=begin html + + +

notice

+ + +=end html +1; diff --git a/fhem/FHEM/FhemUtils/update-20130127-001 b/fhem/FHEM/FhemUtils/update-20130127-001 new file mode 100644 index 000000000..4cc8a3175 --- /dev/null +++ b/fhem/FHEM/FhemUtils/update-20130127-001 @@ -0,0 +1,138 @@ +# FROM: M. Fischer +# DATE: 27.01.2013 +# CONFIRM: 1 +# PUBLISH: 0 +# EXPIRE: 0 +# POSITION: before +# KEY_1: sendStatistics +# VAL_1: AttrVal("global","sendStatistics",undef); +# CON_1: !empty +# TITLE_DE: Das FHEM-Projekt moechte Dich um Deine Unterstuetzung bitten! +# NOTICE_DE + HINWEIS: + + Das FHEM-Projekt moechte Dich um Deine Unterstuetzung bitten! + + Im Rahmen der Aktualisierung kann FHEM Informationen ueber diese Installation + an einen zentralen Server uebertragen. Diese Daten beinhalten Angaben ueber + die installierte FHEM-Version, das Betriebssystem und Rechner-Architektur, + die aktuelle Perl-Version, sowie eine Liste der zur Laufzeit definierten + Module (inkl. der Anzahl der Definitionen je Modultyp). Weiterhin werden die + definierten Modelltypen ermittelt. + + Die am FHEM-Projekt beteiligten Entwickler erhalten wertvolle Informationen zu + der Umgebung, in der FHEM installiert ist, und eine Einschaetzung, wie haeufig + die jeweiligen Module eingesetzt werden. Dies kann Auswirkungen auf die + Weiterentwicklung aber auch auf die zeitnahe Bereitstellung von Erweiterungen + und Korrekturen haben. + + Es werden keine personenbezogenen Daten uebertragen und / oder gespeichert. + Die Daten werden nicht an Dritte weitergegeben und nicht fuer kommerzielle + Zwecke verwendet. Sie dienen einzig als Hilfestellung zur Entwicklung und + zur Einschaetzung der Verbreitung von FHEM. + + Eine weiterfuehrende Beschreibung ist der Dokumentation zu dem FHEM-Befehl + 'fheminfo' sowie dem globalen Paramater 'sendStatsistics' zu entnehmen. Eine + Uebersicht der erhobenen Informationen kann jederzeit ueber den Aufruf von + 'fheminfo' abgerufen werden. + + Wenn Du das FHEM-Projekt unterstuetzen moechtest, solltest Du jetzt ueber das + globale Attribut 'sendStatsistics' die automatische Uebermittlung aktivieren: + + attr global sendStatistics onUpdate + + Im Anschluss solltest Du die aktuelle Konfiguration speichern, um diesen + Hinweis nicht erneut angezeigt zu bekommen. Der Updatevorgang kann dann wie + gewohnt fortgesetzt werden. + + Moechtest Du keine automatische Uebermittlung der Daten waehrend der + Aktualisierung, solltest Du nun das globale Attribut 'sendStatistics' auf + 'manually' setzen: + + attr global sendStatistics manually + + Die Uebermittlung der Daten muss manuell ueber den Befehl 'fheminfo send' + erfolgen. + + Moechtest Du niemals Daten ueber die vorhandene FHEM-Installation uebermitteln, + so muss das globale Attribut auf 'never' gesetzt werden: + + attr global sendStatistics never + + Ein Aufruf von 'fheminfo send' ist damit wirkungslos. + + Die obigen Einstellungen koennen jederzeit geaendert werden. Eine Uebersicht + der bereits von anderen Installationen uebermittelten Informationen kann ueber + + http://fhem.de/stats/statistics.cgi + + eingesehen werden. + + Das FHEM-Team freut sich, wenn auch Du durch die automatische Uebermittlung + Deiner technischen Daten zum FHEM-Projekt beitraegst. + + Dieser Hinweistext kann erneut durch den Aufruf von 'update viewAdvice' + angezeigt werden. + + Vielen Dank fuer Deine Unterstuetzung! +# TITLE_EN: The FHEM Project asks for your support! +# NOTICE_EN + The FHEM Project asks for your support! + + During the update process FHEM is able to send statistical information + regarding your installation to a central server. This may include data like + your installed FHEM version, the operating system, Perl version, computer + achitecture and the list of modules used during the update. Also the list of + model types and number of definitions for each module may be collected. + + The developers behind the FHEM project receive valuable information about the + environment in which FHEM is installed and get an overview how often those + modules are used. This may affect the further development of FHEM as well as + the timely provision of extensions and corrections. + + No personal information will be transferred or stored during this process. The + data collected will neither be made available to a third party nor used for + commercial purposes. The only purpose is to support further development of + FHEM and to asses its distribution. + + A more detailed explanation can be found in the documentation related to the + command 'fheminfo' and the global parameter 'sendStatistics'. An overview + about all information collected can be displayed at any time by using the + command 'fheminfo'. + + If you would like to support the FHEM project, you may set the global attribut + 'sendStatistics' to enable the automatic info transfer process. + + attr global sendStatistics onUpdate + + Thereafter you should save the current configuration to avoid this note beeing + displayed again. The update process can be continued like before. + + In case you do not whish an automatic transmission of the data collected + during update, you should set the global attribute 'sendStatistics' to + 'manually': + + attr global sendStatistics manually + + Manual transfer of the data can then be performed by using the command + 'fheminfo send'. + + If you never want to send information about your FHEM installation by all + means, you need to set the global attribut 'sendStatistics' to 'never': + + attr global sendStatistics never + + Even the use of 'fheminfo send' will then not transfer any data. + + All the settings mentioned above can be amended at any time. An overview of + data sent from other installations can be obtained at + + http://fhem.de/stats/statistics.cgi + + The FHEM Project Team would be happy if you considered supporting the + development of FHEM by transferring your technical data to the project. + + This info text can be displayed again by using the command + 'update viewAdvice'. + + Thanks a lot for your support!